From 8bf4a32dfd993650156d2629a3083f12b1973065 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Tue, 16 Feb 2021 19:31:09 +0000 Subject: [PATCH 01/96] Apply translations in hy translation completed for the source file '/cookbook/locale/en/LC_MESSAGES/django.po' on the 'hy' language. --- cookbook/locale/hy/LC_MESSAGES/django.po | 1880 ++++++++++++++++++++++ 1 file changed, 1880 insertions(+) create mode 100644 cookbook/locale/hy/LC_MESSAGES/django.po diff --git a/cookbook/locale/hy/LC_MESSAGES/django.po b/cookbook/locale/hy/LC_MESSAGES/django.po new file mode 100644 index 00000000..44d37706 --- /dev/null +++ b/cookbook/locale/hy/LC_MESSAGES/django.po @@ -0,0 +1,1880 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +# Translators: +# H K , 2021 +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-02-09 18:01+0100\n" +"PO-Revision-Date: 2020-06-02 19:28+0000\n" +"Last-Translator: H K , 2021\n" +"Language-Team: Armenian (https://www.transifex.com/django-recipes/teams/110507/hy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: .\cookbook\filters.py:22 .\cookbook\templates\base.html:87 +#: .\cookbook\templates\forms\edit_internal_recipe.html:219 +#: .\cookbook\templates\forms\ingredients.html:34 +#: .\cookbook\templates\stats.html:28 .\cookbook\views\lists.py:72 +msgid "Ingredients" +msgstr "Բաղադրիչներ" + +#: .\cookbook\forms.py:44 +msgid "" +"Color of the top navigation bar. Not all colors work with all themes, just " +"try them out!" +msgstr "" +"Վերին վահանակի գույնը։ Ոչ բոլոր գույներն են աշխատում բոլոր թեմաների հետ, " +"պարզապես փորձեք։" + +#: .\cookbook\forms.py:45 +msgid "Default Unit to be used when inserting a new ingredient into a recipe." +msgstr "Նոր բաղադրիչ ավելացնելիս չափի լռելյայն միավորը։" + +#: .\cookbook\forms.py:46 +msgid "" +"Enables support for fractions in ingredient amounts (e.g. convert decimals " +"to fractions automatically)" +msgstr "" +"Ակտիվացնել բաղադրիչների քանակի համար կոտորակների աջակցությունը (փոխակերպել " +"տասնորդականները կոտորակների)" + +#: .\cookbook\forms.py:47 +msgid "" +"Users with whom newly created meal plan/shopping list entries should be " +"shared by default." +msgstr "" +"Օգտատերեր, ում հետ նոր ստեղծված ճաշացուցակները/գնումների ցուցակները պետք է " +"կիսվեն լռելյայն" + +#: .\cookbook\forms.py:48 +msgid "Show recently viewed recipes on search page." +msgstr "Ցույց տալ վերջերս դիտած բաղադրատոմսերը փնտրման էջում։" + +#: .\cookbook\forms.py:49 +msgid "Number of decimals to round ingredients." +msgstr "Բաղադրիչների կլորացման համար տասնորդականների քանակը" + +#: .\cookbook\forms.py:50 +msgid "If you want to be able to create and see comments underneath recipes." +msgstr "" +"Եթե ցանկանում եք կարողանալ ավելացնել և տեսնել մեկնաբանություններ " +"բաղադրատոմսերի ներքևում։" + +#: .\cookbook\forms.py:52 +msgid "" +"Setting to 0 will disable auto sync. When viewing a shopping list the list " +"is updated every set seconds to sync changes someone else might have made. " +"Useful when shopping with multiple people but might use a little bit of " +"mobile data. If lower than instance limit it is reset when saving." +msgstr "" +"0-ն կանջատի ավտոմատ սինքրոնացումը։ Գնումների ցուցակը թարմացվում է " +"յուրաքանչյուր սահմանված վարկյանը մեկ, մեկ ուրիշի կատարած փոփոխությունները " +"սինքրոնացնելու համար։ Հարմար է, երբ մեկից ավել մարդ է կատարում գնումները, " +"բայց կարող է օգտագործել բջջային ինտերնետ։" + +#: .\cookbook\forms.py:55 +msgid "Makes the navbar stick to the top of the page." +msgstr "Կցել նավիգացիոն տողը էջի վերևում" + +#: .\cookbook\forms.py:71 +msgid "" +"Both fields are optional. If none are given the username will be displayed " +"instead" +msgstr "" +"Երկու դաշտն էլ կամավոր են։ Դատարկ լինելու դեպքում օգտվողի անունը կցուցադրվի " +"փոխարենը" + +#: .\cookbook\forms.py:92 .\cookbook\forms.py:113 .\cookbook\forms.py:277 +#: .\cookbook\templates\forms\edit_internal_recipe.html:45 +msgid "Name" +msgstr "Անվանում" + +#: .\cookbook\forms.py:93 .\cookbook\forms.py:114 .\cookbook\forms.py:278 +#: .\cookbook\templates\base.html:94 +#: .\cookbook\templates\forms\edit_internal_recipe.html:71 +#: .\cookbook\templates\stats.html:24 .\cookbook\templates\url_import.html:183 +msgid "Keywords" +msgstr "Բանալի բառեր" + +#: .\cookbook\forms.py:94 .\cookbook\forms.py:115 +msgid "Preparation time in minutes" +msgstr "Պատրաստման տևողությունը րոպեներով" + +#: .\cookbook\forms.py:95 .\cookbook\forms.py:116 +msgid "Waiting time (cooking/baking) in minutes" +msgstr "Սպասման տևողությունը (եփել/թխել) րոպեներով" + +#: .\cookbook\forms.py:96 .\cookbook\forms.py:279 +msgid "Path" +msgstr "Ուղի" + +#: .\cookbook\forms.py:97 +msgid "Storage UID" +msgstr "Պահոցի UID" + +#: .\cookbook\forms.py:117 +msgid "Number of servings" +msgstr "Չափաբաժինների քանակը" + +#: .\cookbook\forms.py:128 +msgid "" +"Include - [ ] in list for easier usage in markdown based " +"documents." +msgstr "" +"Ներառել - [ ] ցուցակում markdown փաստաթղթերում հեշտ կիրառման " +"համար։" + +#: .\cookbook\forms.py:143 +msgid "Default" +msgstr "Լռելյայն" + +#: .\cookbook\forms.py:162 +msgid "New Unit" +msgstr "Նոր միավոր" + +#: .\cookbook\forms.py:163 +msgid "New unit that other gets replaced by." +msgstr "Նոր միավոր հները փոխարինելու համար։" + +#: .\cookbook\forms.py:168 +msgid "Old Unit" +msgstr "Հին միավոր" + +#: .\cookbook\forms.py:169 +msgid "Unit that should be replaced." +msgstr "Փոխարինման ենթակա միավոր" + +#: .\cookbook\forms.py:179 +msgid "New Food" +msgstr "Նոր սննդամթերք" + +#: .\cookbook\forms.py:180 +msgid "New food that other gets replaced by." +msgstr "Նոր սննդամթերք, որով փոխարինվում է հինը։" + +#: .\cookbook\forms.py:185 +msgid "Old Food" +msgstr "Հին սննդամթերք" + +#: .\cookbook\forms.py:186 +msgid "Food that should be replaced." +msgstr "Փոխարինման ենթակա սննդամթերք։" + +#: .\cookbook\forms.py:198 +msgid "Add your comment: " +msgstr "Ավելացրեք ձեր մեկնաբանությունը՝" + +#: .\cookbook\forms.py:229 +msgid "Leave empty for dropbox and enter app password for nextcloud." +msgstr "" +"Թողնել դատարկ dropbox-ի համար և մուտքագրել ծրագրի գաղտնաբառը nextcloud-ի " +"համար։" + +#: .\cookbook\forms.py:236 +msgid "Leave empty for nextcloud and enter api token for dropbox." +msgstr "" +"Թողնել դատարկ nextcloud-ի համար և մուտքագրել ծրագրի ժետոնը dropbox-ի համար։" + +#: .\cookbook\forms.py:244 +msgid "" +"Leave empty for dropbox and enter only base url for nextcloud " +"(/remote.php/webdav/ is added automatically)" +msgstr "" +"Թողնել դատարկ dropbox-ի համար և մուտքագրել միայն հիմքային հղումը nextcloud-ի" +" համար (/remote.php/webdav/ ինքնաբերաբար ավելացվում է)" + +#: .\cookbook\forms.py:263 +msgid "Search String" +msgstr "Փնտրել շարքը" + +#: .\cookbook\forms.py:280 +msgid "File ID" +msgstr "Ֆայլի ID" + +#: .\cookbook\forms.py:299 +msgid "You must provide at least a recipe or a title." +msgstr "Դուք պետք է տրամադրեք առնվազն բաղադրատոմս կամ վերնագիր" + +#: .\cookbook\forms.py:312 +msgid "You can list default users to share recipes with in the settings." +msgstr "" +"Դուք կարող եք կարգավորումներում ավելացնել այն օգտատերերին, ում հետ " +"բաղադրատոմսերը պետք է կիսվեն լռելյայն" + +#: .\cookbook\forms.py:313 +#: .\cookbook\templates\forms\edit_internal_recipe.html:377 +msgid "" +"You can use markdown to format this field. See the docs here" +msgstr "" +"Դուք կարող եք օգտագործել markdown-ն այս դաշտը ձևավորելու համար. Տեսեք փաստաթղթերն այստեղ" + +#: .\cookbook\forms.py:328 +msgid "A username is not required, if left blank the new user can choose one." +msgstr "" +"Օգտատերի անուն պարտադիր չէ, դատարկ թողնելու դեպքում նոր օգտատերը կարող է " +"անձամբ ընտրել։" + +#: .\cookbook\helper\permission_helper.py:137 +#: .\cookbook\helper\permission_helper.py:206 +#: .\cookbook\helper\permission_helper.py:220 +#: .\cookbook\helper\permission_helper.py:231 +#: .\cookbook\helper\permission_helper.py:242 .\cookbook\views\data.py:32 +#: .\cookbook\views\views.py:106 .\cookbook\views\views.py:218 +msgid "You do not have the required permissions to view this page!" +msgstr "Դուք չունեք անհրաժեշտ թույլտվություն այս էջը դիտելու համար։" + +#: .\cookbook\helper\permission_helper.py:151 +msgid "You are not logged in and therefore cannot view this page!" +msgstr "Դուք մուտք չեք գործել, հետևաբար չեք կարող տեսնել այս էջը։" + +#: .\cookbook\helper\permission_helper.py:161 +#: .\cookbook\helper\permission_helper.py:177 +#: .\cookbook\helper\permission_helper.py:192 .\cookbook\views\delete.py:146 +msgid "You cannot interact with this object as it is not owned by you!" +msgstr "Դուք չեք կարող փոփոխել այս օբյեկտը, որովհետև այն չի պատկանում ձեզ։" + +#: .\cookbook\helper\recipe_url_import.py:39 +msgid "The requested site provided malformed data and cannot be read." +msgstr "Հարցված կայքը տրամադրեց վատ ձևավորված տվյալներ և չի կարող կարդացվել։" + +#: .\cookbook\helper\recipe_url_import.py:53 +msgid "" +"The requested site does not provide any recognized data format to import the" +" recipe from." +msgstr "" +"Հարցված կայքը չի տրամադրում որևէ ճանաչելի տվյալ բաղադրատոմսը ներմուծելու " +"համար։" + +#: .\cookbook\helper\recipe_url_import.py:177 +msgid "Imported from" +msgstr "Ներմուծվել է՝" + +#: .\cookbook\integration\integration.py:97 +msgid "" +"Importer expected a .zip file. Did you choose the correct importer type for " +"your data ?" +msgstr "" +"Ներմուծողն ակնկալում էր .zip ֆայլ։ Արդյո՞ք ձեր ֆայլին համապատասխանող ճիշտ " +"տեսակի ներմուծող եք ընտրել։" + +#: .\cookbook\integration\safron.py:23 +#: .\cookbook\templates\forms\edit_internal_recipe.html:65 +#: .\cookbook\templates\include\log_cooking.html:16 +#: .\cookbook\templates\url_import.html:65 +msgid "Servings" +msgstr "Չափաբաժիններ" + +#: .\cookbook\integration\safron.py:25 +msgid "Waiting time" +msgstr "Սպասման տևողություն" + +#: .\cookbook\integration\safron.py:27 +#: .\cookbook\templates\forms\edit_internal_recipe.html:59 +msgid "Preparation Time" +msgstr "Պատրաստման տևողություն" + +#: .\cookbook\integration\safron.py:29 .\cookbook\templates\base.html:67 +#: .\cookbook\templates\forms\ingredients.html:7 +#: .\cookbook\templates\index.html:7 +msgid "Cookbook" +msgstr "Խոհարարական գիրք " + +#: .\cookbook\integration\safron.py:31 +msgid "Section" +msgstr "Բաժին" + +#: .\cookbook\migrations\0047_auto_20200602_1133.py:12 +msgid "Breakfast" +msgstr "Նախաճաշ" + +#: .\cookbook\migrations\0047_auto_20200602_1133.py:17 +msgid "Lunch" +msgstr "Ճաշ" + +#: .\cookbook\migrations\0047_auto_20200602_1133.py:22 +msgid "Dinner" +msgstr "Ընթրիք" + +#: .\cookbook\migrations\0047_auto_20200602_1133.py:27 +msgid "Other" +msgstr "Այլ" + +#: .\cookbook\models.py:77 .\cookbook\templates\shopping_list.html:48 +msgid "Search" +msgstr "Փնտրել" + +#: .\cookbook\models.py:78 .\cookbook\templates\base.html:81 +#: .\cookbook\templates\meal_plan.html:5 .\cookbook\views\delete.py:165 +#: .\cookbook\views\edit.py:216 .\cookbook\views\new.py:189 +msgid "Meal-Plan" +msgstr "Ճաշացուցակ" + +#: .\cookbook\models.py:79 .\cookbook\templates\base.html:78 +msgid "Books" +msgstr "Գրքեր" + +#: .\cookbook\models.py:86 +msgid "Small" +msgstr "Փոքր" + +#: .\cookbook\models.py:86 +msgid "Large" +msgstr "Մեծ" + +#: .\cookbook\models.py:242 +#: .\cookbook\templates\forms\edit_internal_recipe.html:198 +msgid "Text" +msgstr "Տեքստ" + +#: .\cookbook\models.py:242 +#: .\cookbook\templates\forms\edit_internal_recipe.html:199 +msgid "Time" +msgstr "Ժամանակ" + +#: .\cookbook\tables.py:35 .\cookbook\templates\books.html:36 +#: .\cookbook\templates\generic\edit_template.html:6 +#: .\cookbook\templates\generic\edit_template.html:14 +#: .\cookbook\templates\meal_plan.html:281 +#: .\cookbook\templates\recipes_table.html:77 +#: .\cookbook\templates\shopping_list.html:33 +msgid "Edit" +msgstr "Խմբագրել" + +#: .\cookbook\tables.py:124 .\cookbook\tables.py:147 +#: .\cookbook\templates\books.html:38 +#: .\cookbook\templates\generic\delete_template.html:5 +#: .\cookbook\templates\generic\delete_template.html:13 +#: .\cookbook\templates\generic\edit_template.html:27 +#: .\cookbook\templates\meal_plan.html:277 +msgid "Delete" +msgstr "Ջնջել" + +#: .\cookbook\tables.py:144 +msgid "Link" +msgstr "Հղում" + +#: .\cookbook\templates\404.html:5 +msgid "404 Error" +msgstr "Սխալ 404" + +#: .\cookbook\templates\404.html:18 +msgid "The page you are looking for could not be found." +msgstr "Ձեր փնտրած էջը հնարավոր չէ գտնել։" + +#: .\cookbook\templates\404.html:33 +msgid "Take me Home" +msgstr "Գնալ տուն" + +#: .\cookbook\templates\404.html:35 +msgid "Report a Bug" +msgstr "Զեկուցել սխալի մասին" + +#: .\cookbook\templates\account\login.html:7 +#: .\cookbook\templates\base.html:166 +msgid "Login" +msgstr "Մուտք" + +#: .\cookbook\templates\account\login.html:13 +#: .\cookbook\templates\account\login.html:28 +msgid "Sign In" +msgstr "Մուտք գործել" + +#: .\cookbook\templates\account\login.html:38 +msgid "Social Login" +msgstr "Մուտք Սոցիալական էջով" + +#: .\cookbook\templates\account\login.html:39 +msgid "You can use any of the following providers to sign in." +msgstr "" +"Դուք կարող եք օգտագործել հետևյալ պրովայդերներից ցանկացածը մուտք գործելու " +"համար։" + +#: .\cookbook\templates\account\logout.html:5 +#: .\cookbook\templates\account\logout.html:9 +#: .\cookbook\templates\account\logout.html:18 +msgid "Sign Out" +msgstr "Դուրս գալ" + +#: .\cookbook\templates\account\logout.html:11 +msgid "Are you sure you want to sign out?" +msgstr "Համոզվա՞ծ եք, որ ցանկանում եք դուրս գալ" + +#: .\cookbook\templates\account\password_reset.html:5 +#: .\cookbook\templates\account\password_reset_done.html:5 +msgid "Password Reset" +msgstr "Գաղտնաբառի վերականգնում" + +#: .\cookbook\templates\account\password_reset.html:9 +#: .\cookbook\templates\account\password_reset_done.html:9 +msgid "Password reset is not implemented for the time being!" +msgstr "Գաղտնաբառի վերականգնում առայժմ իրականացված չէ" + +#: .\cookbook\templates\account\signup.html:5 +msgid "Register" +msgstr "Գրանցվել" + +#: .\cookbook\templates\account\signup.html:9 +msgid "Create your Account" +msgstr "Ստեղծեք ձեր հաշիվը" + +#: .\cookbook\templates\account\signup.html:14 +msgid "Create User" +msgstr "Ստեղծել օգտատեր" + +#: .\cookbook\templates\api_info.html:5 .\cookbook\templates\base.html:156 +#: .\cookbook\templates\rest_framework\api.html:11 +msgid "API Documentation" +msgstr "API-ի փաստաթղթեր" + +#: .\cookbook\templates\base.html:74 +msgid "Utensils" +msgstr "Գործիքակազմ" + +#: .\cookbook\templates\base.html:84 +msgid "Shopping" +msgstr "Գնումներ" + +#: .\cookbook\templates\base.html:98 .\cookbook\views\delete.py:84 +#: .\cookbook\views\edit.py:83 .\cookbook\views\lists.py:26 +#: .\cookbook\views\new.py:62 +msgid "Keyword" +msgstr "Բանալի բառ" + +#: .\cookbook\templates\base.html:100 +msgid "Batch Edit" +msgstr "Խմբային խմբագրում" + +#: .\cookbook\templates\base.html:105 +msgid "Storage Data" +msgstr "Պահոցի տվյալներ" + +#: .\cookbook\templates\base.html:109 +msgid "Storage Backends" +msgstr "Պահոցի բեքենդեր" + +#: .\cookbook\templates\base.html:111 +msgid "Configure Sync" +msgstr "Կարգավորել սինքրոնիզացիան" + +#: .\cookbook\templates\base.html:113 +msgid "Discovered Recipes" +msgstr "Հայտնաբերված բաղադրատոմսեր" + +#: .\cookbook\templates\base.html:115 +msgid "Discovery Log" +msgstr "Բացահայտումների մատյան" + +#: .\cookbook\templates\base.html:117 .\cookbook\templates\stats.html:10 +msgid "Statistics" +msgstr "Վիճակագրություն " + +#: .\cookbook\templates\base.html:119 +msgid "Units & Ingredients" +msgstr "Միավորներ և բաղադրիչներ" + +#: .\cookbook\templates\base.html:121 +msgid "Import Recipe" +msgstr "Ներմուծել բաղադրատոմս" + +#: .\cookbook\templates\base.html:140 .\cookbook\templates\settings.html:6 +#: .\cookbook\templates\settings.html:16 +msgid "Settings" +msgstr "Կարգավորումներ" + +#: .\cookbook\templates\base.html:142 .\cookbook\templates\history.html:6 +#: .\cookbook\templates\history.html:14 +msgid "History" +msgstr "Պատմություն" + +#: .\cookbook\templates\base.html:146 .\cookbook\templates\system.html:13 +msgid "System" +msgstr "Համակարգ" + +#: .\cookbook\templates\base.html:148 +msgid "Admin" +msgstr "Ադմինիստրատոր" + +#: .\cookbook\templates\base.html:152 +msgid "Markdown Guide" +msgstr "Markdown-ի ուղեցույց" + +#: .\cookbook\templates\base.html:154 +msgid "GitHub" +msgstr "GitHub" + +#: .\cookbook\templates\base.html:158 +msgid "API Browser" +msgstr "API բրաուզեր" + +#: .\cookbook\templates\base.html:161 +msgid "Logout" +msgstr "Դուրս գալ" + +#: .\cookbook\templates\batch\edit.html:6 +msgid "Batch edit Category" +msgstr "Կատեգորիաների խմբային խմբագրում" + +#: .\cookbook\templates\batch\edit.html:15 +msgid "Batch edit Recipes" +msgstr "Բաղադրատոմսերի խմբային խմբագրում" + +#: .\cookbook\templates\batch\edit.html:20 +msgid "Add the specified keywords to all recipes containing a word" +msgstr "" +"Ավելացնել նշված բանալի բառերը բոլոր բաղադրատոմսերին, որոնք պարունակում են " +"բառ" + +#: .\cookbook\templates\batch\monitor.html:6 .\cookbook\views\edit.py:66 +msgid "Sync" +msgstr "Սինքրոնիզացնել" + +#: .\cookbook\templates\batch\monitor.html:10 +msgid "Manage watched Folders" +msgstr "Կարգավորել դիտվող թղթապանակները" + +#: .\cookbook\templates\batch\monitor.html:14 +msgid "" +"On this Page you can manage all storage folder locations that should be " +"monitored and synced." +msgstr "" +"Այս էջում կարող եք կարգավորել այն պահպաման թղթապանակները, որոնք պետք է " +"վերահսկվեն և սինքրոնիզացվեն։" + +#: .\cookbook\templates\batch\monitor.html:16 +msgid "The path must be in the following format" +msgstr "Ուղին պետք է լինի հետևյալ ձևաչափով՝" + +#: .\cookbook\templates\batch\monitor.html:27 +msgid "Sync Now!" +msgstr "Սինքրոնիզացնել հիմա։" + +#: .\cookbook\templates\batch\waiting.html:4 +#: .\cookbook\templates\batch\waiting.html:10 +msgid "Importing Recipes" +msgstr "Բաղադրատոմսերի ներմուծում" + +#: .\cookbook\templates\batch\waiting.html:23 +msgid "" +"This can take a few minutes, depending on the number of recipes in sync, " +"please wait." +msgstr "" +"Կախված սինքրոնիզացվող բաղադրատոմսերի քանակից, պրոցեսը կարող է տևել մի քանի " +"րոպե, խնդրում ենք սպասել։" + +#: .\cookbook\templates\books.html:5 .\cookbook\templates\books.html:11 +msgid "Recipe Books" +msgstr "Բաղադրատոմսերի գիրք" + +#: .\cookbook\templates\books.html:15 +msgid "New Book" +msgstr "Նոր գիրք" + +#: .\cookbook\templates\books.html:27 .\cookbook\templates\recipe_view.html:26 +msgid "by" +msgstr "Հեղինակ" + +#: .\cookbook\templates\books.html:34 +msgid "Toggle Recipes" +msgstr "Փոխանջատել Բաղադրատոմսերը" + +#: .\cookbook\templates\books.html:54 +#: .\cookbook\templates\meal_plan_entry.html:48 +#: .\cookbook\templates\recipes_table.html:59 +msgid "Last cooked" +msgstr "Վերջին պատրաստումը" + +#: .\cookbook\templates\books.html:71 +msgid "There are no recipes in this book yet." +msgstr "Այս գրքում բաղադրատոմսեր դեռ չկան։" + +#: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6 +msgid "Export Recipes" +msgstr "Արտահանել բաղադրատոմսերը" + +#: .\cookbook\templates\export.html:14 .\cookbook\templates\export.html:20 +#: .\cookbook\templates\shopping_list.html:345 +#: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20 +msgid "Export" +msgstr "Արտահանել" + +#: .\cookbook\templates\forms\edit_import_recipe.html:5 +#: .\cookbook\templates\forms\edit_import_recipe.html:9 +msgid "Import new Recipe" +msgstr "Ներմուծել նոր բաղադրատոմս" + +#: .\cookbook\templates\forms\edit_import_recipe.html:14 +#: .\cookbook\templates\forms\edit_internal_recipe.html:389 +#: .\cookbook\templates\forms\edit_internal_recipe.html:421 +#: .\cookbook\templates\generic\edit_template.html:23 +#: .\cookbook\templates\generic\new_template.html:23 +#: .\cookbook\templates\include\log_cooking.html:28 +#: .\cookbook\templates\meal_plan.html:325 +#: .\cookbook\templates\settings.html:28 .\cookbook\templates\settings.html:35 +#: .\cookbook\templates\settings.html:58 .\cookbook\templates\settings.html:73 +#: .\cookbook\templates\shopping_list.html:347 +msgid "Save" +msgstr "Պահպանել" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:7 +#: .\cookbook\templates\forms\edit_internal_recipe.html:34 +msgid "Edit Recipe" +msgstr "Խմբագրել բաղադրատոմսը" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:62 +msgid "Waiting Time" +msgstr "Սպասման տևողություն" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:68 +msgid "Servings Text" +msgstr "Չափաբաժինների տեքստ" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:79 +msgid "Select Keywords" +msgstr "Ընտրել բանալի բառեր" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:93 +msgid "Description" +msgstr "Նկարագրություն" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:108 +msgid "Nutrition" +msgstr "Սննդայնություն" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:112 +#: .\cookbook\templates\forms\edit_internal_recipe.html:162 +msgid "Delete Step" +msgstr "Ջնջել քայլը" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:116 +msgid "Calories" +msgstr "Կալորիաներ" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:119 +msgid "Carbohydrates" +msgstr "Ածխաջրեր" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:122 +msgid "Fats" +msgstr "Ճարպեր" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:124 +msgid "Proteins" +msgstr "Սպիտակուցներ" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:146 +#: .\cookbook\templates\forms\edit_internal_recipe.html:454 +msgid "Step" +msgstr "Քայլ" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:167 +msgid "Show as header" +msgstr "Ցույց տալ որպես խորագիր" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:173 +msgid "Hide as header" +msgstr "Թաքցնել որպես խորագիր" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:178 +msgid "Move Up" +msgstr "Բարձրացնել" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:183 +msgid "Move Down" +msgstr "Իջեցնել" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:192 +msgid "Step Name" +msgstr "Քայլի անվանում" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:196 +msgid "Step Type" +msgstr "Քայլի տեսակ" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:207 +msgid "Step time in Minutes" +msgstr "Քայլի տևողությունը րոպեներով" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:261 +#: .\cookbook\templates\shopping_list.html:181 +msgid "Select Unit" +msgstr "Ընտրել միավորը" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:262 +#: .\cookbook\templates\forms\edit_internal_recipe.html:286 +#: .\cookbook\templates\shopping_list.html:182 +#: .\cookbook\templates\shopping_list.html:204 +msgid "Create" +msgstr "Ստեղծել" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:263 +#: .\cookbook\templates\forms\edit_internal_recipe.html:287 +#: .\cookbook\templates\shopping_list.html:183 +#: .\cookbook\templates\shopping_list.html:205 +#: .\cookbook\templates\shopping_list.html:235 +#: .\cookbook\templates\shopping_list.html:259 +#: .\cookbook\templates\url_import.html:105 +#: .\cookbook\templates\url_import.html:137 +msgid "Select" +msgstr "Ընտրել" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:285 +#: .\cookbook\templates\shopping_list.html:203 +msgid "Select Food" +msgstr "Ընտրել սննդամթերք" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:302 +#: .\cookbook\templates\meal_plan.html:256 +#: .\cookbook\templates\url_import.html:152 +msgid "Note" +msgstr "Նոթեր" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:319 +msgid "Delete Ingredient" +msgstr "Ջնջել բաղադրիչը" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:325 +msgid "Make Header" +msgstr "Ստեղծել Խորագիր" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:331 +msgid "Make Ingredient" +msgstr "Ստեղծել բաղդրիչ" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:337 +msgid "Disable Amount" +msgstr "Անջատել քանակը" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:343 +msgid "Enable Amount" +msgstr "Միացնել քանակը" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:348 +msgid "Copy Template Reference" +msgstr "Պատճենել ձևանմուշի հղումը" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:374 +#: .\cookbook\templates\url_import.html:177 +msgid "Instructions" +msgstr "Հրահանգներ" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:387 +#: .\cookbook\templates\forms\edit_internal_recipe.html:418 +msgid "Save & View" +msgstr "Պահպանել և Դիտել" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:391 +#: .\cookbook\templates\forms\edit_internal_recipe.html:424 +msgid "Add Step" +msgstr "Ավելացնել քայլ" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:394 +#: .\cookbook\templates\forms\edit_internal_recipe.html:428 +msgid "Add Nutrition" +msgstr "Ավելացնել Սննդայնություն" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:396 +#: .\cookbook\templates\forms\edit_internal_recipe.html:430 +msgid "Remove Nutrition" +msgstr "Հեռացնել Սննդայնություն" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:398 +#: .\cookbook\templates\forms\edit_internal_recipe.html:433 +msgid "View Recipe" +msgstr "Դիտել բաղադրատոմսը" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:400 +#: .\cookbook\templates\forms\edit_internal_recipe.html:435 +msgid "Delete Recipe" +msgstr "Ջնջել բաղադրատոմսը" + +#: .\cookbook\templates\forms\edit_internal_recipe.html:441 +msgid "Steps" +msgstr "Քայլեր" + +#: .\cookbook\templates\forms\ingredients.html:15 +msgid "Edit Ingredients" +msgstr "Խմբագրել բաղադրիչները" + +#: .\cookbook\templates\forms\ingredients.html:16 +msgid "" +"\n" +" The following form can be used if, accidentally, two (or more) units or ingredients where created that should be\n" +" the same.\n" +" It merges two units or ingredients and updates all recipes using them.\n" +" " +msgstr "" +"\n" +" Հետևյալ բլանկը կարող է օգտագործվել, եթե երկու (կամ ավելի) միավորներ կամ բաղադրիչներ ստեղծվել են սխալմամբ, սակայն պետք է լինեն \n" +" նույնը։\n" +" Սա միավորում է երկու միավորները կամ բաղադրիչները և թարմացնում դրանք օգտագործող բոլոր բաղադրատոմսերը։ \n" +" " + +#: .\cookbook\templates\forms\ingredients.html:24 +#: .\cookbook\templates\stats.html:26 +msgid "Units" +msgstr "Միավորներ" + +#: .\cookbook\templates\forms\ingredients.html:26 +msgid "Are you sure that you want to merge these two units?" +msgstr "Համոզվա՞ծ եք, որ ցանկանում եք միավորել այս երկու միավորները։" + +#: .\cookbook\templates\forms\ingredients.html:31 +#: .\cookbook\templates\forms\ingredients.html:40 +msgid "Merge" +msgstr "Միավորել" + +#: .\cookbook\templates\forms\ingredients.html:36 +msgid "Are you sure that you want to merge these two ingredients?" +msgstr "Համոզվա՞ծ եք, որ ցանկանում եք միավորել այս երկու բաղադրիչները։" + +#: .\cookbook\templates\generic\delete_template.html:18 +#, python-format +msgid "Are you sure you want to delete the %(title)s: %(object)s " +msgstr "Համոզվա՞ծ եք, որ ուզում եք ջնջել %(title)s: %(object)s " + +#: .\cookbook\templates\generic\delete_template.html:21 +msgid "Confirm" +msgstr "Հաստատել" + +#: .\cookbook\templates\generic\edit_template.html:30 +msgid "View" +msgstr "Դիտել" + +#: .\cookbook\templates\generic\edit_template.html:34 +msgid "Delete original file" +msgstr "Ջնջել բնօրինակ ֆայլը" + +#: .\cookbook\templates\generic\list_template.html:6 +#: .\cookbook\templates\generic\list_template.html:12 +msgid "List" +msgstr "Ցուցակ" + +#: .\cookbook\templates\generic\list_template.html:25 +msgid "Filter" +msgstr "Ֆիլտր" + +#: .\cookbook\templates\generic\list_template.html:30 +msgid "Import all" +msgstr "Ներմուծել բոլորը" + +#: .\cookbook\templates\generic\new_template.html:6 +#: .\cookbook\templates\generic\new_template.html:14 +#: .\cookbook\templates\meal_plan.html:323 +msgid "New" +msgstr "Նոր" + +#: .\cookbook\templates\generic\table_template.html:76 +#: .\cookbook\templates\recipes_table.html:112 +msgid "previous" +msgstr "նախորդ" + +#: .\cookbook\templates\generic\table_template.html:98 +#: .\cookbook\templates\recipes_table.html:134 +msgid "next" +msgstr "հաջորդ" + +#: .\cookbook\templates\history.html:20 +msgid "View Log" +msgstr "Դիտումների մատյան" + +#: .\cookbook\templates\history.html:24 +msgid "Cook Log" +msgstr "Եփելու մատյան" + +#: .\cookbook\templates\import.html:6 .\cookbook\templates\test.html:6 +msgid "Import Recipes" +msgstr "Ներմուծել բաղադրատոմսերը" + +#: .\cookbook\templates\import.html:14 .\cookbook\templates\import.html:20 +#: .\cookbook\templates\test.html:14 .\cookbook\templates\test.html:20 +#: .\cookbook\templates\url_import.html:211 .\cookbook\views\delete.py:60 +#: .\cookbook\views\edit.py:182 +msgid "Import" +msgstr "Ներմուծել" + +#: .\cookbook\templates\include\log_cooking.html:7 +msgid "Log Recipe Cooking" +msgstr "Գրանցել բաղադրատոմսի օգտագործում" + +#: .\cookbook\templates\include\log_cooking.html:13 +msgid "All fields are optional and can be left empty." +msgstr "Բոլոր դաշտերը կամավոր են և կարող են դատարկ թողնվել" + +#: .\cookbook\templates\include\log_cooking.html:19 +msgid "Rating" +msgstr "Վարկանիշ" + +#: .\cookbook\templates\include\log_cooking.html:27 +#: .\cookbook\templates\include\recipe_open_modal.html:18 +#: .\cookbook\templates\meal_plan.html:283 +#: .\cookbook\templates\meal_plan.html:327 +#: .\cookbook\templates\meal_plan.html:366 +msgid "Close" +msgstr "Փակել" + +#: .\cookbook\templates\include\recipe_open_modal.html:7 +#: .\cookbook\templates\meal_plan.html:247 .\cookbook\views\delete.py:28 +#: .\cookbook\views\edit.py:262 .\cookbook\views\new.py:40 +msgid "Recipe" +msgstr "Բաղադրատոմս" + +#: .\cookbook\templates\include\recipe_open_modal.html:32 +msgid "Open Recipe" +msgstr "Բացել բաղադրատոմսը" + +#: .\cookbook\templates\include\storage_backend_warning.html:4 +msgid "Security Warning" +msgstr "Անվտանգության զգուշացում" + +#: .\cookbook\templates\include\storage_backend_warning.html:5 +msgid "" +"\n" +" The Password and Token field are stored as plain text inside the database.\n" +" This is necessary because they are needed to make API requests, but it also increases the risk of\n" +" someone stealing it.
\n" +" To limit the possible damage tokens or accounts with limited access can be used.\n" +" " +msgstr "" +"\n" +" Գաղտնաբառ և ժետոն դաշտերը պահպանվում են որպես հասարակ տեքստ շտեմարանի մեջ։\n" +" Սա անհրաժեշտ է, որովհետև դրանք օգտագործվում են API հարցումների համար, բայց դա նաև ավելացնում է ռիսկը, որ \n" +" ինչ-որ մեկը կգօողանա դրանք։
\n" +" Վնասը սահմանափակելու համար կարող են կիրառվել սահմանափակ թույլտվությամբ ժետոններ կամ հաշիվներ։\n" +" " + +#: .\cookbook\templates\index.html:29 +msgid "Search recipe ..." +msgstr "Փնտրել բաղադրատոմս" + +#: .\cookbook\templates\index.html:44 +msgid "New Recipe" +msgstr "Նոր Բաղադրատոմս" + +#: .\cookbook\templates\index.html:47 +msgid "Website Import" +msgstr "Ներմուծում վեբկայքից" + +#: .\cookbook\templates\index.html:53 +msgid "Advanced Search" +msgstr "Հավելյալ որոնում" + +#: .\cookbook\templates\index.html:57 +msgid "Reset Search" +msgstr "Զրոյացնել որոնումը" + +#: .\cookbook\templates\index.html:85 +msgid "Last viewed" +msgstr "Վերջին դիտածը" + +#: .\cookbook\templates\index.html:87 .\cookbook\templates\meal_plan.html:178 +#: .\cookbook\templates\stats.html:22 +msgid "Recipes" +msgstr "Բաղադրատոմսեր" + +#: .\cookbook\templates\index.html:94 +msgid "Log in to view recipes" +msgstr "Մուտք գործեք բաղադրատոմսերը դիտելու համար" + +#: .\cookbook\templates\markdown_info.html:5 +#: .\cookbook\templates\markdown_info.html:13 +msgid "Markdown Info" +msgstr "Markdown-ի մասին տեղեկություն" + +#: .\cookbook\templates\markdown_info.html:14 +msgid "" +"\n" +" Markdown is lightweight markup language that can be used to format plain text easily.\n" +" This site uses the Python Markdown library to\n" +" convert your text into nice looking HTML. Its full markdown documentation can be found\n" +" here.\n" +" An incomplete but most likely sufficient documentation can be found below.\n" +" " +msgstr "" +"\n" +" Markdown-ը թեթև markup լեզու է, որը կարող է օգտագործվել պարզ տեքստը ձևավորելու համար։\n" +" Այս կայքն օգտագործում էPython Markdown գրադարանը\n" +" ձեր տեքստը գեղեցիկ HTML-ի ձևափոխելու համար։ Markdown-ի ամբողջական ուղեցույցերը կարող եք գտնել\n" +" այստեղ։\n" +" Ոչ լրիվ, բայց հավանաբար բավարար ուղեցույցեր կարող եք գտնել ներքևում։\n" +" " + +#: .\cookbook\templates\markdown_info.html:25 +msgid "Headers" +msgstr "Խորագրեր" + +#: .\cookbook\templates\markdown_info.html:54 +msgid "Formatting" +msgstr "Ձևավորում" + +#: .\cookbook\templates\markdown_info.html:56 +#: .\cookbook\templates\markdown_info.html:72 +msgid "Line breaks are inserted by adding two spaces after the end of a line" +msgstr "Տողերի տրոհում կարելի է տեղադրել տողի վերջում ավելացնելող երկու բացատ" + +#: .\cookbook\templates\markdown_info.html:57 +#: .\cookbook\templates\markdown_info.html:73 +msgid "or by leaving a blank line inbetween." +msgstr "կամ դատարկ տող թողնելով։" + +#: .\cookbook\templates\markdown_info.html:59 +#: .\cookbook\templates\markdown_info.html:74 +msgid "This text is bold" +msgstr "Այս տեքստը թավ տառատեսակով է" + +#: .\cookbook\templates\markdown_info.html:60 +#: .\cookbook\templates\markdown_info.html:75 +msgid "This text is italic" +msgstr "Այս տեքստը շեղատառ է" + +#: .\cookbook\templates\markdown_info.html:61 +#: .\cookbook\templates\markdown_info.html:77 +msgid "Blockquotes are also possible" +msgstr "Blockquote-ներ նույնպես հնարավոր են" + +#: .\cookbook\templates\markdown_info.html:84 +msgid "Lists" +msgstr "Ցուցակներ" + +#: .\cookbook\templates\markdown_info.html:85 +msgid "" +"Lists can ordered or unorderd. It is important to leave a blank line " +"before the list!" +msgstr "" +"Ցուցակները կարող են լինել կարգավորված կամ անկարգավորված։ Շատկարևոր է " +"թողնել դատարկ տող ցուցաից առաջ։" + +#: .\cookbook\templates\markdown_info.html:87 +#: .\cookbook\templates\markdown_info.html:108 +msgid "Ordered List" +msgstr "Կարգավորված ցուցակ" + +#: .\cookbook\templates\markdown_info.html:89 +#: .\cookbook\templates\markdown_info.html:90 +#: .\cookbook\templates\markdown_info.html:91 +#: .\cookbook\templates\markdown_info.html:110 +#: .\cookbook\templates\markdown_info.html:111 +#: .\cookbook\templates\markdown_info.html:112 +msgid "unordered list item" +msgstr "չկարգավորված ցուցակի իր" + +#: .\cookbook\templates\markdown_info.html:93 +#: .\cookbook\templates\markdown_info.html:114 +msgid "Unordered List" +msgstr "Չկարգավորված ցուցակ" + +#: .\cookbook\templates\markdown_info.html:95 +#: .\cookbook\templates\markdown_info.html:96 +#: .\cookbook\templates\markdown_info.html:97 +#: .\cookbook\templates\markdown_info.html:116 +#: .\cookbook\templates\markdown_info.html:117 +#: .\cookbook\templates\markdown_info.html:118 +msgid "ordered list item" +msgstr "կարգավորված ցուցակի իր" + +#: .\cookbook\templates\markdown_info.html:125 +msgid "Images & Links" +msgstr "Նկարներ և հղումներ" + +#: .\cookbook\templates\markdown_info.html:126 +msgid "" +"Links can be formatted with Markdown. This application also allows to paste " +"links directly into markdown fields without any formatting." +msgstr "" +"Հղումները կարող են խմբագրվել Markdown-ի օգնությամբ։ Այս ծրագրում հնարավոր է " +"անմիջապես տեղադրել հղումներ markdown դաշտում առանց որևէ խմբագրման։" + +#: .\cookbook\templates\markdown_info.html:132 +#: .\cookbook\templates\markdown_info.html:145 +msgid "This will become an image" +msgstr "Սա կդառնա նկար" + +#: .\cookbook\templates\markdown_info.html:152 +msgid "Tables" +msgstr "Աղյուսակներ" + +#: .\cookbook\templates\markdown_info.html:153 +msgid "" +"Markdown tables are hard to create by hand. It is recommended to use a table" +" editor like this one." +msgstr "" +"Markdown աղյուսակները դժվար է ստեղծել ձեռքով։ Խորհուրդ է տրվում օգտագործել " +"աղյուսակների խմբագիր, օրինակ այս մեկը։" + +#: .\cookbook\templates\markdown_info.html:155 +#: .\cookbook\templates\markdown_info.html:157 +#: .\cookbook\templates\markdown_info.html:171 +#: .\cookbook\templates\markdown_info.html:177 +msgid "Table" +msgstr "Աղյուսակ" + +#: .\cookbook\templates\markdown_info.html:155 +#: .\cookbook\templates\markdown_info.html:172 +msgid "Header" +msgstr "Խորագիր" + +#: .\cookbook\templates\markdown_info.html:157 +#: .\cookbook\templates\markdown_info.html:178 +msgid "Cell" +msgstr "Բջիջ" + +#: .\cookbook\templates\meal_plan.html:101 +msgid "New Entry" +msgstr "Նոր գրառում" + +#: .\cookbook\templates\meal_plan.html:113 +#: .\cookbook\templates\shopping_list.html:52 +msgid "Search Recipe" +msgstr "Փնտրել բաղադրատոմս" + +#: .\cookbook\templates\meal_plan.html:139 +msgid "Title" +msgstr "Վերնագիր" + +#: .\cookbook\templates\meal_plan.html:141 +msgid "Note (optional)" +msgstr "Նոթեր (կամավոր)" + +#: .\cookbook\templates\meal_plan.html:143 +msgid "" +"You can use markdown to format this field. See the docs " +"here" +msgstr "" +"Դուք կարող եք օգտագործել markdown-ն այս դաշտը ձևավորելու համար. Տեսեք փաստաթղթերն այստեղ" + +#: .\cookbook\templates\meal_plan.html:147 +#: .\cookbook\templates\meal_plan.html:251 +msgid "Serving Count" +msgstr "Չափաբաժինների քանակ" + +#: .\cookbook\templates\meal_plan.html:153 +msgid "Create only note" +msgstr "Ստեղծել միայն նոթեր" + +#: .\cookbook\templates\meal_plan.html:168 +#: .\cookbook\templates\shopping_list.html:7 +#: .\cookbook\templates\shopping_list.html:29 +#: .\cookbook\templates\shopping_list.html:693 +msgid "Shopping List" +msgstr "Գնումների ցուցակ" + +#: .\cookbook\templates\meal_plan.html:172 +msgid "Shopping list currently empty" +msgstr "Գնումների ցուցակը դատարկ է" + +#: .\cookbook\templates\meal_plan.html:175 +msgid "Open Shopping List" +msgstr "Բացել գնումների ցուցակը" + +#: .\cookbook\templates\meal_plan.html:189 +msgid "Plan" +msgstr "Պլան" + +#: .\cookbook\templates\meal_plan.html:196 +msgid "Number of Days" +msgstr "Օրերի քանակ" + +#: .\cookbook\templates\meal_plan.html:206 +msgid "Weekday offset" +msgstr "Աշխատանքային օրերի փոխհատուցում" + +#: .\cookbook\templates\meal_plan.html:209 +msgid "" +"Number of days starting from the first day of the week to offset the default" +" view." +msgstr "" +"Շաբաթվա առաջին օրվանից հաշված օրերի քանակը, որը պետք է փոխհատուցել լռելյայն " +"էջում" + +#: .\cookbook\templates\meal_plan.html:217 +#: .\cookbook\templates\meal_plan.html:294 +msgid "Edit plan types" +msgstr "Խմբագրել ճաշացուցակների տեսակները" + +#: .\cookbook\templates\meal_plan.html:219 +msgid "Show help" +msgstr "Ցուցադրել օգնություն" + +#: .\cookbook\templates\meal_plan.html:220 +msgid "Week iCal export" +msgstr "Շաբաթվա արտահանում iCal ձևաչափով" + +#: .\cookbook\templates\meal_plan.html:264 +#: .\cookbook\templates\meal_plan_entry.html:18 +msgid "Created by" +msgstr "Ստեղծող" + +#: .\cookbook\templates\meal_plan.html:270 +#: .\cookbook\templates\meal_plan_entry.html:20 +#: .\cookbook\templates\shopping_list.html:248 +msgid "Shared with" +msgstr "Ու՞մ հետ է կիսվել" + +#: .\cookbook\templates\meal_plan.html:280 +msgid "Add to Shopping" +msgstr "Ավելացնել գնումներին" + +#: .\cookbook\templates\meal_plan.html:323 +msgid "New meal type" +msgstr "Կերակրի նոր տեսակ" + +#: .\cookbook\templates\meal_plan.html:338 +msgid "Meal Plan Help" +msgstr "Ճաշացուցակի Օգնություն" + +#: .\cookbook\templates\meal_plan.html:344 +msgid "" +"\n" +"

The meal plan module allows planning of meals both with recipes and notes.

\n" +"

Simply select a recipe from the list of recently viewed recipes or search the one you\n" +" want and drag it to the desired plan position. You can also add a note and a title and\n" +" then drag the recipe to create a plan entry with a custom title and note. Creating only\n" +" Notes is possible by dragging the create note box into the plan.

\n" +"

Click on a recipe in order to open the detailed view. There you can also add it to the\n" +" shopping list. You can also add all recipes of a day to the shopping list by\n" +" clicking the shopping cart at the top of the table.

\n" +"

Since a common use case is to plan meals together you can define\n" +" users you want to share your plan with in the settings.\n" +"

\n" +"

You can also edit the types of meals you want to plan. If you share your plan with\n" +" someone with\n" +" different meals, their meal types will appear in your list as well. To prevent\n" +" duplicates (e.g. Other and Misc.)\n" +" name your meal types the same as the users you share your meals with and they will be\n" +" merged.

\n" +" " +msgstr "" +"\n" +"

Ճաշացուցակի մոդուլը թույլ է տալիս պլանավորել ճաշերը բաղադրատոմսերով և նոթերով։

\n" +"

Պարզապես ընտրեք բաղադրատոմս վերջերս դիտած բաղադրատոմսերի ցուցակից կամ փնտրեք այն բաղադրատոմսը,\n" +" որն ուզում եք և քաշեք ընտրված ճաշացուցակի դիրք։ Դուք կարող եք նաև ավելացնել նոթեր և վերնագիր, ապա\n" +" քաշեք բաղադրատոմսը ձեր ընտրած վերնագրով և նոթերով ցուցակ ստեղծելու համար։ Միայն\n" +" նոթեր ստեղծելը նույնպես հնարավոր է, եթե քաշեք «ստեղծել միայն նոթեր» պատուհանը դեպի ցուցակ։

\n" +"

Սեղմեք որևէ բաղադրատոմսի վրա մանրամասներով պատուհանը բացելու համար։ Այդտեղից կարող եք այն նաև ավելացնել\n" +" գնումների ցուցակ։ Դուք կարող եք նաև ավելացնել օրվա բոլոր բաղադրատոմսերը գնումների ցուցակ\n" +" սեղմելով գնումների սայլակի նշանի վրա։

\n" +"

Քանի որ ընդունված է ճաշեր պլանավորել միասին, դուք կարող եք կարգավորումներում հստակեցնել\n" +" օգտատերերին ում հետ ցանկանում եք կիսվել ձեր ցուցակով։\n" +"

\n" +"

Դուք կարող եք նաև խմբագրել ճաշերի տեսակը, որը ցանկանում եք պլանավորել։ Եթե կիսվեք ձեր պլանով\n" +" որևէ մեկի հետ, ով\n" +" ունի ուրիշ ճաշեր, նրանց ճաշերի տեսակները նույնպես կհայտնվեն ձեր ցուցակում։ Կրկնօրինակներից (օրինակ ընթրիք և ընթրիքներ)\n" +" խուսաբելու համար\n" +" օգտագործեք միևնույն ճաշի տեսակների անունն այն մարդկանց պես, ում հետ ցանկանում եք կիսվել և դրանք\n" +" կմիավորվեն։

\n" +" " + +#: .\cookbook\templates\meal_plan_entry.html:6 +msgid "Meal Plan View" +msgstr "Ճաշացուցակի Դիտման էջ" + +#: .\cookbook\templates\meal_plan_entry.html:50 +msgid "Never cooked before." +msgstr "Երբեք պատրաստված չէ" + +#: .\cookbook\templates\meal_plan_entry.html:76 +msgid "Other meals on this day" +msgstr "Նույն օրվա այլ ճաշեր" + +#: .\cookbook\templates\no_groups_info.html:5 +#: .\cookbook\templates\offline.html:6 +msgid "Offline" +msgstr "Ցանցից դուրս" + +#: .\cookbook\templates\no_groups_info.html:12 +msgid "No Permissions" +msgstr "Թույլտվություն չկա" + +#: .\cookbook\templates\no_groups_info.html:15 +msgid "" +"You do not have any groups and therefor cannot use this application. Please " +"contact your administrator." +msgstr "" +"Դուք չունեք որևէ խումբ և չեք կարող օգտագործել այս ծրագիրը։ Կապվեք ձեր " +"ադմինիստրատորի հետ։" + +#: .\cookbook\templates\offline.html:19 +msgid "You are currently offline!" +msgstr "Դուք ցանցից դուրս եք։" + +#: .\cookbook\templates\offline.html:20 +msgid "" +"The recipes listed below are available for offline viewing because you have " +"recently viewed them. Keep in mind that data might be outdated." +msgstr "" +"Ներքևում նշված բաղադրատոմսերը հասանելի են ցանցից դուրս դիտման համար, " +"որովհետև դուք դիտել եք դրանք վերջերս։ Հիշեք, որ տվյալները կարող են հնացած " +"լինել։" + +#: .\cookbook\templates\recipe_view.html:21 .\cookbook\templates\stats.html:47 +msgid "Comments" +msgstr "Մեկնաբանություններ" + +#: .\cookbook\templates\recipe_view.html:44 .\cookbook\views\delete.py:118 +#: .\cookbook\views\edit.py:162 +msgid "Comment" +msgstr "Մեկնաբանել" + +#: .\cookbook\templates\recipes_table.html:19 +#: .\cookbook\templates\recipes_table.html:23 +#: .\cookbook\templates\url_import.html:50 +msgid "Recipe Image" +msgstr "Բաղադրատոմսի նկար" + +#: .\cookbook\templates\recipes_table.html:46 +#: .\cookbook\templates\url_import.html:55 +msgid "Preparation time ca." +msgstr "Պատրաստման տևողություն" + +#: .\cookbook\templates\recipes_table.html:52 +#: .\cookbook\templates\url_import.html:60 +msgid "Waiting time ca." +msgstr "Սպասման տևողություն" + +#: .\cookbook\templates\recipes_table.html:55 +msgid "External" +msgstr "Արտաքին" + +#: .\cookbook\templates\recipes_table.html:81 +msgid "Log Cooking" +msgstr "Գրանցել եփել" + +#: .\cookbook\templates\rest_framework\api.html:5 +msgid "Recipe Home" +msgstr "Բաղադրատոմսի տուն" + +#: .\cookbook\templates\settings.html:22 +msgid "Account" +msgstr "Հաշիվ" + +#: .\cookbook\templates\settings.html:38 +msgid "Link social account" +msgstr "Կցել սոցիալական հաշիվ" + +#: .\cookbook\templates\settings.html:42 +msgid "Language" +msgstr "Լեզու" + +#: .\cookbook\templates\settings.html:67 +msgid "Style" +msgstr "Ոճ" + +#: .\cookbook\templates\settings.html:79 +msgid "API Token" +msgstr "API ժետոն" + +#: .\cookbook\templates\settings.html:80 +msgid "" +"You can use both basic authentication and token based authentication to " +"access the REST API." +msgstr "" +"Դուք կարող եք օգտագործել ինչպես հասարակ այնպես էլ ժետոնով նույնականացում " +"REST API-ին հասանելիության համար։" + +#: .\cookbook\templates\settings.html:92 +msgid "" +"Use the token as an Authorization header prefixed by the word token as shown" +" in the following examples:" +msgstr "" +"Օգտագործեք ժետոնը որպես Թույլտվության խորագիր, նախածանցված բառ ժետոնով, " +"ինչպես ցույց է տրված հետևյալ օրինակում․" + +#: .\cookbook\templates\settings.html:94 +msgid "or" +msgstr "կամ" + +#: .\cookbook\templates\setup.html:6 .\cookbook\templates\system.html:5 +msgid "Cookbook Setup" +msgstr "Խոհարարական գրքի կարգավորում" + +#: .\cookbook\templates\setup.html:14 +msgid "Setup" +msgstr "Կարգավորում" + +#: .\cookbook\templates\setup.html:15 +msgid "" +"To start using this application you must first create a superuser account." +msgstr "" +"Այս ծրագիրն օգտագործելու համար նախ պետք է ստեղծեք սուպեր-օգտատերի հաշիվ" + +#: .\cookbook\templates\setup.html:20 +msgid "Create Superuser account" +msgstr "Ստեղծել սուպեր-օգտատերի հաշիվ" + +#: .\cookbook\templates\shopping_list.html:75 +msgid "Shopping Recipes" +msgstr "Գնումների բաղադրատոմսեր" + +#: .\cookbook\templates\shopping_list.html:79 +msgid "No recipes selected" +msgstr "Բաղադրատոմս ընտրված չէ" + +#: .\cookbook\templates\shopping_list.html:145 +msgid "Entry Mode" +msgstr "Գրառման ռեժիմ" + +#: .\cookbook\templates\shopping_list.html:153 +msgid "Add Entry" +msgstr "Ավելացնել գրառում" + +#: .\cookbook\templates\shopping_list.html:168 +msgid "Amount" +msgstr "Քանակ" + +#: .\cookbook\templates\shopping_list.html:224 +msgid "Supermarket" +msgstr "Սուպերմարկետ" + +#: .\cookbook\templates\shopping_list.html:234 +msgid "Select Supermarket" +msgstr "Ընտրել Սուպերմարկետ" + +#: .\cookbook\templates\shopping_list.html:258 +msgid "Select User" +msgstr "Ընտրել օգտատեր" + +#: .\cookbook\templates\shopping_list.html:277 +msgid "Finished" +msgstr "Ավարտված է" + +#: .\cookbook\templates\shopping_list.html:290 +msgid "You are offline, shopping list might not syncronize." +msgstr "Դուք ցանցից դուրս եք, գնումների ցուցակը կարող է չսինքրոնիզացվել։" + +#: .\cookbook\templates\shopping_list.html:353 +msgid "Copy/Export" +msgstr "Պատճենել/Արտահանել" + +#: .\cookbook\templates\shopping_list.html:357 +msgid "List Prefix" +msgstr "Ցուցակի նախածանց" + +#: .\cookbook\templates\shopping_list.html:696 +msgid "There was an error creating a resource!" +msgstr "Ռեսուրսը ստեղծելիս սխալ է գրանցվել" + +#: .\cookbook\templates\socialaccount\connections.html:4 +#: .\cookbook\templates\socialaccount\connections.html:7 +msgid "Account Connections" +msgstr "Հաշվի կապեր" + +#: .\cookbook\templates\socialaccount\connections.html:10 +msgid "" +"You can sign in to your account using any of the following third party\n" +" accounts:" +msgstr "" +"Դուք կարող եք մուտք գործել ձեր հաշիվ օգտագործելով հետևյալ երրորդ կողմի\n" +" հաշիվները․" + +#: .\cookbook\templates\socialaccount\connections.html:36 +msgid "Remove" +msgstr "Հեռացնել" + +#: .\cookbook\templates\socialaccount\connections.html:44 +msgid "" +"You currently have no social network accounts connected to this account." +msgstr "Դուք այս հաշվին կապված սոցիալական հաշիվներ չունեք " + +#: .\cookbook\templates\socialaccount\connections.html:47 +msgid "Add a 3rd Party Account" +msgstr "Ավելացնել 3րդ կողմի հաշիվ" + +#: .\cookbook\templates\stats.html:4 +msgid "Stats" +msgstr "Վիճակագրություն" + +#: .\cookbook\templates\stats.html:19 +msgid "Number of objects" +msgstr "Օբյեկտների քանակը" + +#: .\cookbook\templates\stats.html:30 +msgid "Recipe Imports" +msgstr "Բաղադրատոմսի ներմուծումներ" + +#: .\cookbook\templates\stats.html:38 +msgid "Objects stats" +msgstr "Օբյեկտների վիճակագրություն" + +#: .\cookbook\templates\stats.html:41 +msgid "Recipes without Keywords" +msgstr "Առանց բանալի բառերի բաղադրատոմսեր" + +#: .\cookbook\templates\stats.html:43 +msgid "External Recipes" +msgstr "Արտաքին բաղադրատոմսեր" + +#: .\cookbook\templates\stats.html:45 +msgid "Internal Recipes" +msgstr "Ներքին բաղադրատոմսեր" + +#: .\cookbook\templates\system.html:21 .\cookbook\views\lists.py:128 +msgid "Invite Links" +msgstr "Հրավերի հղումներ" + +#: .\cookbook\templates\system.html:22 +msgid "Show Links" +msgstr "Ցուցադրել հղումները" + +#: .\cookbook\templates\system.html:27 +msgid "Backup & Restore" +msgstr "Կրկնօրինակում և վերականգնում " + +#: .\cookbook\templates\system.html:28 +msgid "Download Backup" +msgstr "Ներբեռնել կրկնօրինակը" + +#: .\cookbook\templates\system.html:49 +msgid "System Information" +msgstr "Համակարգի տեղեկություն" + +#: .\cookbook\templates\system.html:51 +msgid "" +"\n" +" Django Recipes is an open source free software application. It can be found on\n" +" GitHub.\n" +" Changelogs can be found here.\n" +" " +msgstr "" +"\n" +" Django Բաղադրատոմսերը բաց աղբյուրով անվճար ծրագիր է։ Այն կարող եք գտնել \n" +" GitHub-ում։\n" +" Փոփոխությունների մատյանը կարող եք գտնել այստեղ։\n" +" " + +#: .\cookbook\templates\system.html:65 +msgid "Media Serving" +msgstr "Մեդիայի մատուցում" + +#: .\cookbook\templates\system.html:66 .\cookbook\templates\system.html:81 +#: .\cookbook\templates\system.html:97 +msgid "Warning" +msgstr "Զգուշացում" + +#: .\cookbook\templates\system.html:66 .\cookbook\templates\system.html:81 +#: .\cookbook\templates\system.html:97 .\cookbook\templates\system.html:112 +msgid "Ok" +msgstr "Լավ է" + +#: .\cookbook\templates\system.html:68 +msgid "" +"Serving media files directly using gunicorn/python is not recommend!\n" +" Please follow the steps described\n" +" here to update\n" +" your installation.\n" +" " +msgstr "" +"Մեդիա ֆայլերի մատուցումը gunicorn/python-ի կիրառմամբ խորհուրդ չէ տրվում։\n" +" Խնդրում ենք օգտագործել քայլերը նկարագրված\n" +" այստեղ ձեր տեղադրումը\n" +" թարմացնելու համար։\n" +" " + +#: .\cookbook\templates\system.html:74 .\cookbook\templates\system.html:90 +#: .\cookbook\templates\system.html:105 .\cookbook\templates\system.html:119 +msgid "Everything is fine!" +msgstr "Ամեն բան նորմալ է։" + +#: .\cookbook\templates\system.html:79 +msgid "Secret Key" +msgstr "Գաղտնի բանալի" + +#: .\cookbook\templates\system.html:83 +msgid "" +"\n" +" You do not have a SECRET_KEY configured in your .env file. Django defaulted to the\n" +" standard key\n" +" provided with the installation which is publicly know and insecure! Please set\n" +" SECRET_KEY int the .env configuration file.\n" +" " +msgstr "" +"\n" +" Դուք չունեք SECRET_KEY մատնանշված ձեր .env ֆայլում. Django-ն օգտագործում է\n" +" ստանդարտ բանալի\n" +" տրված ծրագրի ներդրման ժամանակ, ինչը հանրային է և ոչ անվտանգ։ Խնդրում ենք մատնանշել\n" +" SECRET_KEY բանալի .env Ֆայլում։\n" +" " + +#: .\cookbook\templates\system.html:95 +msgid "Debug Mode" +msgstr "Վրիպակների վերացման ռեժիմ" + +#: .\cookbook\templates\system.html:99 +msgid "" +"\n" +" This application is still running in debug mode. This is most likely not needed. Turn of debug mode by\n" +" setting\n" +" DEBUG=0 int the .env configuration file.\n" +" " +msgstr "" +"\n" +" Այս ծրագիրը դեռ աշխատում է վրիպակների վերացման ռեժիմում։ Սա հավանաբար անհրաժեշտ չէ։ Անժատեք այս ռեժիմը\n" +" սահմանելով\n" +" DEBUG=0 .env կազմաձևումների ֆայլում։\n" +" " + +#: .\cookbook\templates\system.html:110 +msgid "Database" +msgstr "Շտեմարան" + +#: .\cookbook\templates\system.html:112 +msgid "Info" +msgstr "Տեղեկություն" + +#: .\cookbook\templates\system.html:114 +msgid "" +"\n" +" This application is not running with a Postgres database backend. This is ok but not recommended as some\n" +" features only work with postgres databases.\n" +" " +msgstr "" +"\n" +" Այս ծրագիրը չի աշխատում Postgres շտեմարան բեքենդով։ Դա նորմալ է, բայց խորհուրդ չի տրվում որովհետև որոշ\n" +" հատկություններ աշխատում են միայն postgres շտեմարանների հետ։\n" +" " + +#: .\cookbook\templates\url_import.html:5 +msgid "URL Import" +msgstr "URL ներմուծում" + +#: .\cookbook\templates\url_import.html:23 +msgid "Enter website URL" +msgstr "Մուտքագրեք վեբկայքի URL-ը" + +#: .\cookbook\templates\url_import.html:44 +msgid "Recipe Name" +msgstr "Բաղադրատոմսի անուն" + +#: .\cookbook\templates\url_import.html:104 +#: .\cookbook\templates\url_import.html:136 +#: .\cookbook\templates\url_import.html:192 +msgid "Select one" +msgstr "Ընտրել մեկը" + +#: .\cookbook\templates\url_import.html:203 +msgid "All Keywords" +msgstr "Բոլոր բանալի բառերը" + +#: .\cookbook\templates\url_import.html:206 +msgid "Import all keywords, not only the ones already existing." +msgstr "Ներմուծել բոլոր բանալի բառերը, ոչ միայն արդեն գոյություն ունեցողները" + +#: .\cookbook\templates\url_import.html:233 +msgid "Information" +msgstr "Տեղեկություն" + +#: .\cookbook\templates\url_import.html:235 +msgid "" +" Only websites containing ld+json or microdata information can currently\n" +" be imported. Most big recipe pages support this. If you site cannot be imported but\n" +" you think\n" +" it probably has some kind of structured data feel free to post an example in the\n" +" github issues." +msgstr "" +" Ներկայումս միայն ld+json կամ microdata տեղեկություն պարունակող կայքերից կարելի է\n" +" ներմուծել։ Բաղադրատոմսերի մեծ կայքերը հիմնականում պարունակում են դա։ Եթե ձեր կայքը հնարավոր չէ ներմուծել, բայց\n" +" կարծում եք\n" +" այն հավանաբար ունի ինչ-որ տեսակի կառուցվածքավորված տվյալ, կարող եք տեղեկացնել մեզ ստեղծելով\n" +" github-ի խնդիր։" + +#: .\cookbook\templates\url_import.html:243 +msgid "Google ld+json Info" +msgstr "Google ld+json-ի տեղեկություն" + +#: .\cookbook\templates\url_import.html:246 +msgid "GitHub Issues" +msgstr "GitHub-ի խնդիրներ" + +#: .\cookbook\templates\url_import.html:248 +msgid "Recipe Markup Specification" +msgstr "Բաղադրատոմսի Markup բնութագրեր" + +#: .\cookbook\views\api.py:104 +msgid "Parameter filter_list incorrectly formatted" +msgstr "filter_list պարամետրը սխալ է ձևավորված" + +#: .\cookbook\views\api.py:117 +msgid "Preference for given user already exists" +msgstr "Այս օգտատերի նախապատվությունն արդեն գոյություն ունի" + +#: .\cookbook\views\api.py:416 .\cookbook\views\views.py:265 +msgid "This feature is not available in the demo version!" +msgstr "Այս հատկությունը հասանելի չէ փորձնական տարբերակում։" + +#: .\cookbook\views\api.py:439 +msgid "Sync successful!" +msgstr "Սինքրոնիզացիան հաջողված է" + +#: .\cookbook\views\api.py:444 +msgid "Error synchronizing with Storage" +msgstr "Պահոցի հետ սինքրոնիզացիայի սխալ" + +#: .\cookbook\views\api.py:510 +msgid "The requested page could not be found." +msgstr "Պահանջվող էջը չի գտնվել" + +#: .\cookbook\views\api.py:519 +msgid "" +"The requested page refused to provide any information (Status Code 403)." +msgstr "" +"Պահանջվող էջը մերժեց տրամադրել որևէ տեղեկություն (Կարգավիճակի ծածկագիր 403)" + +#: .\cookbook\views\data.py:101 +#, python-format +msgid "Batch edit done. %(count)d recipe was updated." +msgid_plural "Batch edit done. %(count)d Recipes where updated." +msgstr[0] "Խմբային խմբագրումն ավարտված է։ %(count)d բաղադրատոմս թարմացված է" +msgstr[1] "Խմբային խմբագրումն ավարտված է։ %(count)d բաղադրատոմս թարմացված է։" + +#: .\cookbook\views\delete.py:72 +msgid "Monitor" +msgstr "Վերահսկել" + +#: .\cookbook\views\delete.py:96 .\cookbook\views\lists.py:109 +#: .\cookbook\views\new.py:83 +msgid "Storage Backend" +msgstr "Պահոցի բեքենդ" + +#: .\cookbook\views\delete.py:106 +msgid "" +"Could not delete this storage backend as it is used in at least one monitor." +msgstr "Չենք կարող ջնջել պահոցի այս բեքենդը, քանի որ այն օգտագործվում է։" + +#: .\cookbook\views\delete.py:129 .\cookbook\views\edit.py:196 +#: .\cookbook\views\new.py:144 +msgid "Recipe Book" +msgstr "Բաղադրատոմսի գիրք" + +#: .\cookbook\views\delete.py:154 +msgid "Bookmarks" +msgstr "Էջանիշեր" + +#: .\cookbook\views\delete.py:176 .\cookbook\views\new.py:214 +msgid "Invite Link" +msgstr "Հրավերի հղում" + +#: .\cookbook\views\edit.py:100 +msgid "Food" +msgstr "Սննդամթերք" + +#: .\cookbook\views\edit.py:110 +msgid "You cannot edit this storage!" +msgstr "Դուք կարող եք խմբագրել այս պահոցը։" + +#: .\cookbook\views\edit.py:131 +msgid "Storage saved!" +msgstr "Պահոցը պահպանված է" + +#: .\cookbook\views\edit.py:137 +msgid "There was an error updating this storage backend!" +msgstr "Պահոցի այս բեքեբդի թարմացման ժամանակ սխալ է գրանցվել։" + +#: .\cookbook\views\edit.py:148 +msgid "Storage" +msgstr "Պահոց" + +#: .\cookbook\views\edit.py:245 +msgid "Changes saved!" +msgstr "Փոփոխությունները պահպանված են" + +#: .\cookbook\views\edit.py:253 +msgid "Error saving changes!" +msgstr "Փոփոխությունների պահպանման սխալ" + +#: .\cookbook\views\edit.py:289 +msgid "Units merged!" +msgstr "Միավորները միավորված են" + +#: .\cookbook\views\edit.py:295 .\cookbook\views\edit.py:317 +msgid "Cannot merge with the same object!" +msgstr "Հնարավոր չէ միավորել նույն օբյեկտի հետ" + +#: .\cookbook\views\edit.py:311 +msgid "Foods merged!" +msgstr "Սննդամթերքները միավորված են" + +#: .\cookbook\views\import_export.py:42 +msgid "Importing is not implemented for this provider" +msgstr "Ներմուծումն այս պրովայդերի համար իրականացված չէ" + +#: .\cookbook\views\import_export.py:58 +msgid "Exporting is not implemented for this provider" +msgstr "Արտահանումն այս պրովայդերի համար իրականացված չէ" + +#: .\cookbook\views\lists.py:42 +msgid "Import Log" +msgstr "Ներմուծման մատյան" + +#: .\cookbook\views\lists.py:55 +msgid "Discovery" +msgstr "Բացահայտել" + +#: .\cookbook\views\lists.py:92 +msgid "Shopping Lists" +msgstr "Գնումների ցուցակներ" + +#: .\cookbook\views\new.py:107 +msgid "Imported new recipe!" +msgstr "Բաղադրատոմսը ներմուծված է" + +#: .\cookbook\views\new.py:114 +msgid "There was an error importing this recipe!" +msgstr "Այս բաղադրատոմսի ներմուծման ժամանակ սխալ է գրանցվել։" + +#: .\cookbook\views\views.py:117 +msgid "You do not have the required permissions to perform this action!" +msgstr "Դուք չունեք բավարար թույլտվություն այս գործողության համար։" + +#: .\cookbook\views\views.py:136 +msgid "Comment saved!" +msgstr "Մեկնաբանությունը պահպանված է" + +#: .\cookbook\views\views.py:152 +msgid "This recipe is already linked to the book!" +msgstr "Բաղադրատոմսն արդեն կապված է գրքին" + +#: .\cookbook\views\views.py:158 +msgid "Bookmark saved!" +msgstr "Էջանիշը պահպանված է" + +#: .\cookbook\views\views.py:380 +msgid "" +"The setup page can only be used to create the first user! If you have " +"forgotten your superuser credentials please consult the django documentation" +" on how to reset passwords." +msgstr "" +"Կարգավորման էջը կարող է օգտագործվել միայն առաջին օգտագործողին ստեղծելու " +"համար։ Եթե մոռացել եք ձեր սուպեր-օգտատերի գաղտնաբառը, խնդրում ենք ստուգել " +"django-ի փաստաթղթերը գաղտնաբառը վերականգնելու ցուցումների համար։" + +#: .\cookbook\views\views.py:388 .\cookbook\views\views.py:435 +msgid "Passwords dont match!" +msgstr "Գաղտնաբառերը չեն համընկնում" + +#: .\cookbook\views\views.py:402 .\cookbook\views\views.py:449 +msgid "User has been created, please login!" +msgstr "Օգտատերը ստեղծված է, խնդրում ենք մուտք գործել։" + +#: .\cookbook\views\views.py:419 +msgid "Malformed Invite Link supplied!" +msgstr "Հրավերի արատավոր հղում է տրամադրվել։" + +#: .\cookbook\views\views.py:470 +msgid "Invite Link not valid or already used!" +msgstr "Հրավերի հղումը վավեր չէ, կամ արդեն օգտագործվել է" From 894d2d2e6b97cefc5b6fbaafe3f073d578cf5239 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Tue, 16 Feb 2021 22:14:40 +0100 Subject: [PATCH 02/96] gracful recipes api error on wrong format of update_at --- cookbook/views/api.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cookbook/views/api.py b/cookbook/views/api.py index b6036ab3..ab480f31 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -9,7 +9,7 @@ from annoying.functions import get_object_or_None from django.contrib import messages from django.contrib.auth.models import User from django.core import management -from django.core.exceptions import FieldError +from django.core.exceptions import FieldError, ValidationError from django.core.files import File from django.db.models import Q from django.http import FileResponse, HttpResponse, JsonResponse @@ -70,6 +70,8 @@ class StandardFilterMixin(ViewSetMixin): queryset = queryset.filter(updated_at__gte=updated_at) except FieldError: pass + except ValidationError: + raise APIException(_('Parameter updated_at incorrectly formatted')) limit = self.request.query_params.get('limit', None) random = self.request.query_params.get('random', False) From e727cae0204b1166510317ea26992403fdcc3ba8 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Feb 2021 09:17:42 +0100 Subject: [PATCH 03/96] fixed typo that broke fractions --- cookbook/static/vue/js/offline_view.js | 2 +- cookbook/static/vue/js/recipe_view.js | 2 +- vue/src/components/Ingredient.vue | 2 +- vue/src/utils/utils.js | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cookbook/static/vue/js/offline_view.js b/cookbook/static/vue/js/offline_view.js index 67d8c3f7..08531bef 100644 --- a/cookbook/static/vue/js/offline_view.js +++ b/cookbook/static/vue/js/offline_view.js @@ -1 +1 @@ -(function(e){function t(t){for(var s,c,o=t[0],f=t[1],i=t[2],u=0,j=[];ut[n.id].updated_at&&(t[n.id]=n):t[n.id]=n)})),t}},data:function(){return{recipes:[],filter:""}},mounted:function(){this.loadRecipe()},methods:{formatDateTime:function(e){return i.a.locale(window.navigator.language),i()(e).format("LLL")},loadRecipe:function(){var e=this;caches.open("api-recipe").then((function(t){t.keys().then((function(t){t.forEach((function(t){caches.match(t).then((function(t){t.json().then((function(t){e.recipes.push(t)}))}))}))}))}))}}},u=d,j=n("2877"),l=Object(j["a"])(u,a,r,!1,null,null,null),b=l.exports;s["default"].config.productionTip=!1,new s["default"]({render:function(e){return e(b)}}).$mount("#app")},fa7d:function(e,t,n){"use strict";n.d(t,"c",(function(){return r})),n.d(t,"f",(function(){return c})),n.d(t,"a",(function(){return o})),n.d(t,"e",(function(){return f})),n.d(t,"b",(function(){return i})),n.d(t,"g",(function(){return d})),n.d(t,"d",(function(){return j}));n("99af");var s=n("59e4");function a(e,t,n){var s=Math.floor(e),a=1,r=s+1,c=1;if(e!==s)while(a<=t&&c<=t){var o=(s+r)/(a+c);if(e===o){a+c<=t?(a+=c,s+=r,c=t+1):a>c?c=t+1:a=t+1;break}et&&(a=c,s=r),!n)return[0,s,a];var f=Math.floor(s/a);return[f,s-f*a,a]}var r={methods:{makeToast:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return c(e,t,n)}}};function c(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new s["a"];a.$bvToast.toast(t,{title:e,variant:n,toaster:"b-toaster-top-center",solid:!0})}var o={methods:{_:function(e){return f(e)}}};function f(e){return window.gettext(e)}var i={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function u(e){return window.USER_PREF[e]}function j(e,t){if(u("user_fractions")){var n="",s=a.cont(e*t,9,!0);return s[0]>0&&(n+=s[0]),s[1]>0&&(n+=" ".concat(s[1],"").concat(s[2],"")),n}return l(e*t)}function l(e){var t=u("user_fractions")?u("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file +(function(e){function t(t){for(var s,c,f=t[0],o=t[1],i=t[2],u=0,j=[];ut[n.id].updated_at&&(t[n.id]=n):t[n.id]=n)})),t}},data:function(){return{recipes:[],filter:""}},mounted:function(){this.loadRecipe()},methods:{formatDateTime:function(e){return i.a.locale(window.navigator.language),i()(e).format("LLL")},loadRecipe:function(){var e=this;caches.open("api-recipe").then((function(t){t.keys().then((function(t){t.forEach((function(t){caches.match(t).then((function(t){t.json().then((function(t){e.recipes.push(t)}))}))}))}))}))}}},u=d,j=n("2877"),l=Object(j["a"])(u,a,r,!1,null,null,null),b=l.exports;s["default"].config.productionTip=!1,new s["default"]({render:function(e){return e(b)}}).$mount("#app")},fa7d:function(e,t,n){"use strict";n.d(t,"c",(function(){return r})),n.d(t,"f",(function(){return c})),n.d(t,"a",(function(){return f})),n.d(t,"e",(function(){return o})),n.d(t,"b",(function(){return i})),n.d(t,"g",(function(){return d})),n.d(t,"d",(function(){return j}));n("99af");var s=n("59e4");function a(e,t,n){var s=Math.floor(e),a=1,r=s+1,c=1;if(e!==s)while(a<=t&&c<=t){var f=(s+r)/(a+c);if(e===f){a+c<=t?(a+=c,s+=r,c=t+1):a>c?c=t+1:a=t+1;break}et&&(a=c,s=r),!n)return[0,s,a];var o=Math.floor(s/a);return[o,s-o*a,a]}var r={methods:{makeToast:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return c(e,t,n)}}};function c(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new s["a"];a.$bvToast.toast(t,{title:e,variant:n,toaster:"b-toaster-top-center",solid:!0})}var f={methods:{_:function(e){return o(e)}}};function o(e){return window.gettext(e)}var i={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function u(e){return window.USER_PREF[e]}function j(e,t){if(u("use_fractions")){var n="",s=a(e*t,9,!0);return s[0]>0&&(n+=s[0]),s[1]>0&&(n+=" ".concat(s[1],"").concat(s[2],"")),n}return l(e*t)}function l(e){var t=u("user_fractions")?u("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file diff --git a/cookbook/static/vue/js/recipe_view.js b/cookbook/static/vue/js/recipe_view.js index a567afe9..8004d610 100644 --- a/cookbook/static/vue/js/recipe_view.js +++ b/cookbook/static/vue/js/recipe_view.js @@ -1 +1 @@ -(function(e){function t(t){for(var i,r,c=t[0],o=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),c=s("5f5b"),o=(s("2dd8"),s("bc3a")),l=s.n(o),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},g=[],b=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",[e._v(e._s(e.calculateAmount(e.ingredient.amount)))]):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,b,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",[e._v(e._s(e.calculateAmount(e.number)))])},E=[],$={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},z=$,T=Object(C["a"])(z,S,E,!1,null,null,null),N=T.exports,P={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:N},template:"
".concat(this.code,"
")})}},M=P,D=Object(C["a"])(M,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),I=s.n(U);i["default"].prototype.moment=I.a;var A={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=I()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=I()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},H=A,B=Object(C["a"])(H,v,g,!1,null,null,null),L=B.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:I()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,ce=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("img",{attrs:{src:e.pdfUrl,width:"100%",height:"700px",alt:e._("External Recipe Image")}})])},oe=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,ce,oe,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.calories))+" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))+" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.fats))+" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.proteins))+" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,ge=Object(C["a"])(ve,ue,me,!1,null,null,null),be=ge.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,$e=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),ze=$e.exports,Te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Ne=[],Pe=s("8e5f"),Me=s.n(Pe);i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Me.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,Te,Ne,!1,null,null,null)),Ie=Ue.exports;i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var Ae={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:L,RecipeContextMenu:ee,Nutrition:be,Keywords:we,LoadingSpinner:ze,AddRecipeToBook:Ie},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var c,o=Object(r["a"])(n.ingredients);try{for(o.s();!(c=o.n()).done;){var l=c.value;t.$set(l,"checked",!1)}}catch(d){o.e(d)}finally{o.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=I()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var c=i.value;c.id===e.id&&this.$set(c,"checked",!c.checked)}}catch(o){n.e(o)}finally{n.f()}}}catch(o){s.e(o)}finally{s.f()}}}},He=Ae,Be=Object(C["a"])(He,a,n,!1,null,null,null),Le=Be.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Le)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return c})),s.d(t,"e",(function(){return o})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var c=(i+n)/(a+r);if(e===c){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var o=Math.floor(i/a);return[o,i-o*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var c={methods:{_:function(e){return o(e)}}};function o(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("user_fractions")){var s="",i=a.cont(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file +(function(e){function t(t){for(var i,r,c=t[0],o=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),c=s("5f5b"),o=(s("2dd8"),s("bc3a")),l=s.n(o),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},g=[],b=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,b,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",[e._v(e._s(e.calculateAmount(e.number)))])},E=[],$={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},T=$,z=Object(C["a"])(T,S,E,!1,null,null,null),P=z.exports,M={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:P},template:"
".concat(this.code,"
")})}},N=M,D=Object(C["a"])(N,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),I=s.n(U);i["default"].prototype.moment=I.a;var A={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=I()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=I()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},H=A,B=Object(C["a"])(H,v,g,!1,null,null,null),L=B.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:I()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,ce=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("img",{attrs:{src:e.pdfUrl,width:"100%",height:"700px",alt:e._("External Recipe Image")}})])},oe=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,ce,oe,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.calories))+" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))+" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.fats))+" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.proteins))+" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,ge=Object(C["a"])(ve,ue,me,!1,null,null,null),be=ge.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,$e=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),Te=$e.exports,ze=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Pe=[],Me=s("8e5f"),Ne=s.n(Me);i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Ne.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,ze,Pe,!1,null,null,null)),Ie=Ue.exports;i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var Ae={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:L,RecipeContextMenu:ee,Nutrition:be,Keywords:we,LoadingSpinner:Te,AddRecipeToBook:Ie},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var c,o=Object(r["a"])(n.ingredients);try{for(o.s();!(c=o.n()).done;){var l=c.value;t.$set(l,"checked",!1)}}catch(d){o.e(d)}finally{o.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=I()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var c=i.value;c.id===e.id&&this.$set(c,"checked",!c.checked)}}catch(o){n.e(o)}finally{n.f()}}}catch(o){s.e(o)}finally{s.f()}}}},He=Ae,Be=Object(C["a"])(He,a,n,!1,null,null,null),Le=Be.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Le)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return c})),s.d(t,"e",(function(){return o})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var c=(i+n)/(a+r);if(e===c){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var o=Math.floor(i/a);return[o,i-o*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var c={methods:{_:function(e){return o(e)}}};function o(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("use_fractions")){var s="",i=a(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file diff --git a/vue/src/components/Ingredient.vue b/vue/src/components/Ingredient.vue index 8cebf42b..5b20373f 100644 --- a/vue/src/components/Ingredient.vue +++ b/vue/src/components/Ingredient.vue @@ -12,7 +12,7 @@ - {{ calculateAmount(ingredient.amount) }} + {{ ingredient.unit.name }} diff --git a/vue/src/utils/utils.js b/vue/src/utils/utils.js index e23be726..96fe8c14 100644 --- a/vue/src/utils/utils.js +++ b/vue/src/utils/utils.js @@ -78,9 +78,9 @@ export function getUserPreference(pref) { import {frac} from "@/utils/fractions"; export function calculateAmount(amount, factor) { - if (getUserPreference('user_fractions')) { + if (getUserPreference('use_fractions')) { let return_string = '' - let fraction = frac.cont((amount * factor), 9, true) + let fraction = frac((amount * factor), 9, true) if (fraction[0] > 0) { return_string += fraction[0] From 73a24a8ef014ebbe44b429e2ae52bfaa9d742113 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Feb 2021 09:29:11 +0100 Subject: [PATCH 04/96] chowdown doc warning --- docs/features/import_export.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/features/import_export.md b/docs/features/import_export.md index 258eb562..4f81d801 100644 --- a/docs/features/import_export.md +++ b/docs/features/import_export.md @@ -63,6 +63,11 @@ Images are saved in a directory called `images`. In order to import your Chowdown recipes simply create a `.zip` file from those two folders and import them. The folder structure should look as follows + +!!! warning "_recipes" + Make sure to add have the `_` before the `recipes` folder but not the `images` folder. This is because chowdown does it + this way by default. + ``` Recipes.zip/ ├── _recipes/ From fef6f695ce0bfcf4f7e6a4b30071220a35437d84 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Feb 2021 09:36:13 +0100 Subject: [PATCH 05/96] chowdown import folder syntax support --- cookbook/integration/chowdown.py | 2 +- docs/features/import_export.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cookbook/integration/chowdown.py b/cookbook/integration/chowdown.py index ecd2c45e..f7a21b5b 100644 --- a/cookbook/integration/chowdown.py +++ b/cookbook/integration/chowdown.py @@ -12,7 +12,7 @@ class Chowdown(Integration): def import_file_name_filter(self, zip_info_object): print("testing", zip_info_object.filename) - return re.match(r'^_recipes/([A-Za-z\d\s-])+.md$', zip_info_object.filename) + return re.match(r'^(_)*recipes/([A-Za-z\d\s-])+.md$', zip_info_object.filename) def get_recipe_from_file(self, file): ingredient_mode = False diff --git a/docs/features/import_export.md b/docs/features/import_export.md index 4f81d801..069687eb 100644 --- a/docs/features/import_export.md +++ b/docs/features/import_export.md @@ -64,9 +64,9 @@ Images are saved in a directory called `images`. In order to import your Chowdown recipes simply create a `.zip` file from those two folders and import them. The folder structure should look as follows -!!! warning "_recipes" - Make sure to add have the `_` before the `recipes` folder but not the `images` folder. This is because chowdown does it - this way by default. +!!! info "_recipes" + For some reason chowdown uses `_` before the `recipes` folder. To avoid confusion the import supports both + `_recipes` and `recipes` ``` Recipes.zip/ From 97cef449c90b7772952f7fcb0d195f92520a9597 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Feb 2021 09:37:17 +0100 Subject: [PATCH 06/96] fixed recipe template rendering scaling issue --- cookbook/static/vue/js/recipe_view.js | 2 +- vue/src/components/ScalableNumber.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook/static/vue/js/recipe_view.js b/cookbook/static/vue/js/recipe_view.js index 8004d610..d89d6915 100644 --- a/cookbook/static/vue/js/recipe_view.js +++ b/cookbook/static/vue/js/recipe_view.js @@ -1 +1 @@ -(function(e){function t(t){for(var i,r,c=t[0],o=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),c=s("5f5b"),o=(s("2dd8"),s("bc3a")),l=s.n(o),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},g=[],b=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,b,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",[e._v(e._s(e.calculateAmount(e.number)))])},E=[],$={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},T=$,z=Object(C["a"])(T,S,E,!1,null,null,null),P=z.exports,M={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:P},template:"
".concat(this.code,"
")})}},N=M,D=Object(C["a"])(N,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),I=s.n(U);i["default"].prototype.moment=I.a;var A={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=I()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=I()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},H=A,B=Object(C["a"])(H,v,g,!1,null,null,null),L=B.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:I()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,ce=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("img",{attrs:{src:e.pdfUrl,width:"100%",height:"700px",alt:e._("External Recipe Image")}})])},oe=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,ce,oe,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.calories))+" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))+" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.fats))+" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.proteins))+" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,ge=Object(C["a"])(ve,ue,me,!1,null,null,null),be=ge.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,$e=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),Te=$e.exports,ze=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Pe=[],Me=s("8e5f"),Ne=s.n(Me);i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Ne.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,ze,Pe,!1,null,null,null)),Ie=Ue.exports;i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var Ae={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:L,RecipeContextMenu:ee,Nutrition:be,Keywords:we,LoadingSpinner:Te,AddRecipeToBook:Ie},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var c,o=Object(r["a"])(n.ingredients);try{for(o.s();!(c=o.n()).done;){var l=c.value;t.$set(l,"checked",!1)}}catch(d){o.e(d)}finally{o.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=I()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var c=i.value;c.id===e.id&&this.$set(c,"checked",!c.checked)}}catch(o){n.e(o)}finally{n.f()}}}catch(o){s.e(o)}finally{s.f()}}}},He=Ae,Be=Object(C["a"])(He,a,n,!1,null,null,null),Le=Be.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Le)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return c})),s.d(t,"e",(function(){return o})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var c=(i+n)/(a+r);if(e===c){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var o=Math.floor(i/a);return[o,i-o*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var c={methods:{_:function(e){return o(e)}}};function o(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("use_fractions")){var s="",i=a(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file +(function(e){function t(t){for(var i,r,c=t[0],o=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),c=s("5f5b"),o=(s("2dd8"),s("bc3a")),l=s.n(o),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},g=[],b=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,b,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.number))}})},E=[],$={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},T=$,z=Object(C["a"])(T,S,E,!1,null,null,null),P=z.exports,M={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:P},template:"
".concat(this.code,"
")})}},N=M,D=Object(C["a"])(N,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),I=s.n(U);i["default"].prototype.moment=I.a;var A={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=I()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=I()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},H=A,L=Object(C["a"])(H,v,g,!1,null,null,null),B=L.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:I()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,ce=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("img",{attrs:{src:e.pdfUrl,width:"100%",height:"700px",alt:e._("External Recipe Image")}})])},oe=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,ce,oe,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.calories))+" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))+" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.fats))+" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.proteins))+" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,ge=Object(C["a"])(ve,ue,me,!1,null,null,null),be=ge.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,$e=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),Te=$e.exports,ze=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Pe=[],Me=s("8e5f"),Ne=s.n(Me);i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Ne.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,ze,Pe,!1,null,null,null)),Ie=Ue.exports;i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var Ae={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:B,RecipeContextMenu:ee,Nutrition:be,Keywords:we,LoadingSpinner:Te,AddRecipeToBook:Ie},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var c,o=Object(r["a"])(n.ingredients);try{for(o.s();!(c=o.n()).done;){var l=c.value;t.$set(l,"checked",!1)}}catch(d){o.e(d)}finally{o.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=I()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var c=i.value;c.id===e.id&&this.$set(c,"checked",!c.checked)}}catch(o){n.e(o)}finally{n.f()}}}catch(o){s.e(o)}finally{s.f()}}}},He=Ae,Le=Object(C["a"])(He,a,n,!1,null,null,null),Be=Le.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Be)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return c})),s.d(t,"e",(function(){return o})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var c=(i+n)/(a+r);if(e===c){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var o=Math.floor(i/a);return[o,i-o*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var c={methods:{_:function(e){return o(e)}}};function o(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("use_fractions")){var s="",i=a(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file diff --git a/vue/src/components/ScalableNumber.vue b/vue/src/components/ScalableNumber.vue index 3f1184b5..2054c6c1 100644 --- a/vue/src/components/ScalableNumber.vue +++ b/vue/src/components/ScalableNumber.vue @@ -1,5 +1,5 @@ From b6b505c36135654c6575ba3974ad479ee703cc96 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Feb 2021 11:11:07 +0100 Subject: [PATCH 07/96] fixed nutrition scaling fractiosn --- cookbook/static/vue/js/recipe_view.js | 2 +- vue/src/components/Nutrition.vue | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cookbook/static/vue/js/recipe_view.js b/cookbook/static/vue/js/recipe_view.js index d89d6915..28609447 100644 --- a/cookbook/static/vue/js/recipe_view.js +++ b/cookbook/static/vue/js/recipe_view.js @@ -1 +1 @@ -(function(e){function t(t){for(var i,r,c=t[0],o=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),c=s("5f5b"),o=(s("2dd8"),s("bc3a")),l=s.n(o),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},g=[],b=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,b,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.number))}})},E=[],$={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},T=$,z=Object(C["a"])(T,S,E,!1,null,null,null),P=z.exports,M={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:P},template:"
".concat(this.code,"
")})}},N=M,D=Object(C["a"])(N,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),I=s.n(U);i["default"].prototype.moment=I.a;var A={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=I()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=I()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},H=A,L=Object(C["a"])(H,v,g,!1,null,null,null),B=L.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:I()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,ce=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("img",{attrs:{src:e.pdfUrl,width:"100%",height:"700px",alt:e._("External Recipe Image")}})])},oe=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,ce,oe,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.calories))+" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))+" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.fats))+" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[e._v(" "+e._s(e.calculateAmount(e.recipe.nutrition.proteins))+" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,ge=Object(C["a"])(ve,ue,me,!1,null,null,null),be=ge.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,$e=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),Te=$e.exports,ze=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Pe=[],Me=s("8e5f"),Ne=s.n(Me);i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Ne.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,ze,Pe,!1,null,null,null)),Ie=Ue.exports;i["default"].prototype.moment=I.a,i["default"].use(c["a"]);var Ae={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:B,RecipeContextMenu:ee,Nutrition:be,Keywords:we,LoadingSpinner:Te,AddRecipeToBook:Ie},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var c,o=Object(r["a"])(n.ingredients);try{for(o.s();!(c=o.n()).done;){var l=c.value;t.$set(l,"checked",!1)}}catch(d){o.e(d)}finally{o.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=I()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var c=i.value;c.id===e.id&&this.$set(c,"checked",!c.checked)}}catch(o){n.e(o)}finally{n.f()}}}catch(o){s.e(o)}finally{s.f()}}}},He=Ae,Le=Object(C["a"])(He,a,n,!1,null,null,null),Be=Le.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Be)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return c})),s.d(t,"e",(function(){return o})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var c=(i+n)/(a+r);if(e===c){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var o=Math.floor(i/a);return[o,i-o*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var c={methods:{_:function(e){return o(e)}}};function o(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("use_fractions")){var s="",i=a(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file +(function(e){function t(t){for(var i,r,o=t[0],c=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),o=s("5f5b"),c=(s("2dd8"),s("bc3a")),l=s.n(c),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},g=[],b=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,b,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.number))}})},E=[],T={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},$=T,P=Object(C["a"])($,S,E,!1,null,null,null),M=P.exports,z={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:M},template:"
".concat(this.code,"
")})}},N=z,D=Object(C["a"])(N,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),H=s.n(U);i["default"].prototype.moment=H.a;var I={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=H()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=H()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},A=I,L=Object(C["a"])(A,v,g,!1,null,null,null),B=L.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:H()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,oe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("img",{attrs:{src:e.pdfUrl,width:"100%",height:"700px",alt:e._("External Recipe Image")}})])},ce=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,oe,ce,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.calories))}}),e._v(" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.fats))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.proteins))}}),e._v(" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,ge=Object(C["a"])(ve,ue,me,!1,null,null,null),be=ge.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,Te=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),$e=Te.exports,Pe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Me=[],ze=s("8e5f"),Ne=s.n(ze);i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Ne.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,Pe,Me,!1,null,null,null)),He=Ue.exports;i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var Ie={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:B,RecipeContextMenu:ee,Nutrition:be,Keywords:we,LoadingSpinner:$e,AddRecipeToBook:He},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var o,c=Object(r["a"])(n.ingredients);try{for(c.s();!(o=c.n()).done;){var l=o.value;t.$set(l,"checked",!1)}}catch(d){c.e(d)}finally{c.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=H()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var o=i.value;o.id===e.id&&this.$set(o,"checked",!o.checked)}}catch(c){n.e(c)}finally{n.f()}}}catch(c){s.e(c)}finally{s.f()}}}},Ae=Ie,Le=Object(C["a"])(Ae,a,n,!1,null,null,null),Be=Le.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Be)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return o})),s.d(t,"e",(function(){return c})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var o=(i+n)/(a+r);if(e===o){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var c=Math.floor(i/a);return[c,i-c*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var o={methods:{_:function(e){return c(e)}}};function c(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("use_fractions")){var s="",i=a(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file diff --git a/vue/src/components/Nutrition.vue b/vue/src/components/Nutrition.vue index b2607c40..f1dec712 100644 --- a/vue/src/components/Nutrition.vue +++ b/vue/src/components/Nutrition.vue @@ -15,7 +15,7 @@ {{ _('Calories') }}
- {{ calculateAmount(recipe.nutrition.calories) }} kcal + kcal
@@ -24,8 +24,7 @@ {{ _('Carbohydrates') }}
- - {{ calculateAmount(recipe.nutrition.carbohydrates) }} g + g
@@ -34,7 +33,7 @@ {{ _('Fats') }}
- {{ calculateAmount(recipe.nutrition.fats) }} g + g
@@ -43,7 +42,7 @@ {{ _('Proteins') }}
- {{ calculateAmount(recipe.nutrition.proteins) }} g + g
From c42266b82c876be910e33423a58754d6107abf72 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Fri, 19 Feb 2021 11:53:30 +0100 Subject: [PATCH 08/96] basic space stuff --- cookbook/filters.py | 113 +++++++++++++-------------- cookbook/forms.py | 95 +++++++++++------------ cookbook/models.py | 77 ++++++++++++++++++- cookbook/urls.py | 1 - cookbook/views/api.py | 131 ++++++++++++++++---------------- cookbook/views/import_export.py | 6 +- requirements.txt | 1 + 7 files changed, 249 insertions(+), 175 deletions(-) diff --git a/cookbook/filters.py b/cookbook/filters.py index c1cc8646..2d75bde3 100644 --- a/cookbook/filters.py +++ b/cookbook/filters.py @@ -3,77 +3,78 @@ from django.conf import settings from django.contrib.postgres.search import TrigramSimilarity from django.db.models import Q from django.utils.translation import gettext as _ +from django_scopes import scopes_disabled from cookbook.forms import MultiSelectWidget from cookbook.models import Food, Keyword, Recipe, ShoppingList +with scopes_disabled(): + class RecipeFilter(django_filters.FilterSet): + name = django_filters.CharFilter(method='filter_name') + keywords = django_filters.ModelMultipleChoiceFilter( + queryset=Keyword.objects.all(), + widget=MultiSelectWidget, + method='filter_keywords' + ) + foods = django_filters.ModelMultipleChoiceFilter( + queryset=Food.objects.all(), + widget=MultiSelectWidget, + method='filter_foods', + label=_('Ingredients') + ) -class RecipeFilter(django_filters.FilterSet): - name = django_filters.CharFilter(method='filter_name') - keywords = django_filters.ModelMultipleChoiceFilter( - queryset=Keyword.objects.all(), - widget=MultiSelectWidget, - method='filter_keywords' - ) - foods = django_filters.ModelMultipleChoiceFilter( - queryset=Food.objects.all(), - widget=MultiSelectWidget, - method='filter_foods', - label=_('Ingredients') - ) - - @staticmethod - def filter_keywords(queryset, name, value): - if not name == 'keywords': + @staticmethod + def filter_keywords(queryset, name, value): + if not name == 'keywords': + return queryset + for x in value: + queryset = queryset.filter(keywords=x) return queryset - for x in value: - queryset = queryset.filter(keywords=x) - return queryset - @staticmethod - def filter_foods(queryset, name, value): - if not name == 'foods': + @staticmethod + def filter_foods(queryset, name, value): + if not name == 'foods': + return queryset + for x in value: + queryset = queryset.filter( + steps__ingredients__food__name=x + ).distinct() return queryset - for x in value: - queryset = queryset.filter( - steps__ingredients__food__name=x - ).distinct() - return queryset - @staticmethod - def filter_name(queryset, name, value): - if not name == 'name': + @staticmethod + def filter_name(queryset, name, value): + if not name == 'name': + return queryset + if settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql_psycopg2': # noqa: E501 + queryset = queryset \ + .annotate(similarity=TrigramSimilarity('name', value), ) \ + .filter(Q(similarity__gt=0.1) | Q(name__unaccent__icontains=value)) \ + .order_by('-similarity') + else: + queryset = queryset.filter(name__icontains=value) return queryset - if settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql_psycopg2': # noqa: E501 - queryset = queryset \ - .annotate(similarity=TrigramSimilarity('name', value), ) \ - .filter(Q(similarity__gt=0.1) | Q(name__unaccent__icontains=value)) \ - .order_by('-similarity') - else: - queryset = queryset.filter(name__icontains=value) - return queryset - class Meta: - model = Recipe - fields = ['name', 'keywords', 'foods', 'internal'] + class Meta: + model = Recipe + fields = ['name', 'keywords', 'foods', 'internal'] -class IngredientFilter(django_filters.FilterSet): - name = django_filters.CharFilter(lookup_expr='icontains') + class IngredientFilter(django_filters.FilterSet): + name = django_filters.CharFilter(lookup_expr='icontains') - class Meta: - model = Food - fields = ['name'] + class Meta: + model = Food + fields = ['name'] -class ShoppingListFilter(django_filters.FilterSet): + class ShoppingListFilter(django_filters.FilterSet): - def __init__(self, data=None, *args, **kwargs): - if data is not None: - data = data.copy() - data.setdefault("finished", False) - super(ShoppingListFilter, self).__init__(data, *args, **kwargs) + def __init__(self, data=None, *args, **kwargs): + if data is not None: + data = data.copy() + data.setdefault("finished", False) + super(ShoppingListFilter, self).__init__(data, *args, **kwargs) - class Meta: - model = ShoppingList - fields = ['finished'] + class Meta: + model = ShoppingList + fields = ['finished'] diff --git a/cookbook/forms.py b/cookbook/forms.py index 1d6d0d79..6d8d5dba 100644 --- a/cookbook/forms.py +++ b/cookbook/forms.py @@ -1,6 +1,7 @@ from django import forms from django.forms import widgets from django.utils.translation import gettext_lazy as _ +from django_scopes.forms import SafeModelChoiceField, SafeModelMultipleChoiceField from emoji_picker.widgets import EmojiPickerTextInput from .models import (Comment, Food, InviteLink, Keyword, MealPlan, Recipe, @@ -74,18 +75,13 @@ class UserNameForm(forms.ModelForm): class ExternalRecipeForm(forms.ModelForm): file_path = forms.CharField(disabled=True, required=False) - storage = forms.ModelChoiceField( - queryset=Storage.objects.all(), - disabled=True, - required=False - ) file_uid = forms.CharField(disabled=True, required=False) class Meta: model = Recipe fields = ( - 'name', 'keywords', 'description', 'servings', 'working_time', 'waiting_time', - 'file_path', 'storage', 'file_uid' + 'name', 'description', 'servings', 'working_time', 'waiting_time', + 'file_path', 'file_uid' ) labels = { @@ -96,39 +92,7 @@ class ExternalRecipeForm(forms.ModelForm): 'file_path': _('Path'), 'file_uid': _('Storage UID'), } - widgets = {'keywords': MultiSelectWidget} - - -class InternalRecipeForm(forms.ModelForm): - ingredients = forms.CharField(widget=forms.HiddenInput(), required=False) - - class Meta: - model = Recipe - fields = ( - 'name', 'image', 'working_time', - 'waiting_time', 'servings', 'keywords' - ) - - labels = { - 'name': _('Name'), - 'keywords': _('Keywords'), - 'working_time': _('Preparation time in minutes'), - 'waiting_time': _('Waiting time (cooking/baking) in minutes'), - 'servings': _('Number of servings'), - } - widgets = {'keywords': MultiSelectWidget} - - -class ShoppingForm(forms.Form): - recipe = forms.ModelMultipleChoiceField( - queryset=Recipe.objects.filter(internal=True).all(), - widget=MultiSelectWidget - ) - markdown_format = forms.BooleanField( - help_text=_('Include - [ ] in list for easier usage in markdown based documents.'), # noqa: E501 - required=False, - initial=False - ) + # widgets = {'keywords': MultiSelectWidget} class ImportExportBase(forms.Form): @@ -150,37 +114,44 @@ class ImportForm(ImportExportBase): class ExportForm(ImportExportBase): - recipes = forms.ModelMultipleChoiceField(queryset=Recipe.objects.filter(internal=True).all(), widget=MultiSelectWidget) + recipes = forms.ModelMultipleChoiceField(widget=MultiSelectWidget, queryset=None) + + def __init__(self, *args, **kwargs): + super().__init__() + user = kwargs.pop('user') + self.fields['recipes'].queryset = Recipe.objects.filter(internal=True).filter(space=user.userpreference.space).all() class UnitMergeForm(forms.Form): prefix = 'unit' - new_unit = forms.ModelChoiceField( - queryset=Unit.objects.all(), + new_unit = SafeModelChoiceField( + queryset=Unit.objects.none(), widget=SelectWidget, label=_('New Unit'), help_text=_('New unit that other gets replaced by.'), ) - old_unit = forms.ModelChoiceField( - queryset=Unit.objects.all(), + old_unit = SafeModelChoiceField( + queryset=Unit.objects.none(), widget=SelectWidget, label=_('Old Unit'), help_text=_('Unit that should be replaced.'), ) +# todo spaces form here on + class FoodMergeForm(forms.Form): prefix = 'food' - new_food = forms.ModelChoiceField( - queryset=Food.objects.all(), + new_food = SafeModelChoiceField( + queryset=Food.objects.none(), widget=SelectWidget, label=_('New Food'), help_text=_('New food that other gets replaced by.'), ) - old_food = forms.ModelChoiceField( - queryset=Food.objects.all(), + old_food = SafeModelChoiceField( + queryset=Food.objects.none(), widget=SelectWidget, label=_('Old Food'), help_text=_('Food that should be replaced.'), @@ -215,6 +186,11 @@ class FoodForm(forms.ModelForm): fields = ('name', 'description', 'ignore_shopping', 'recipe', 'supermarket_category') widgets = {'recipe': SelectWidget} + field_classes = { + 'recipe': SafeModelChoiceField, + 'supermarket_category': SafeModelChoiceField, + } + class StorageForm(forms.ModelForm): username = forms.CharField( @@ -252,17 +228,25 @@ class RecipeBookEntryForm(forms.ModelForm): model = RecipeBookEntry fields = ('book',) + field_classes = { + 'book': SafeModelChoiceField, + } + class SyncForm(forms.ModelForm): class Meta: model = Sync fields = ('storage', 'path', 'active') + field_classes = { + 'storage': SafeModelChoiceField, + } + class BatchEditForm(forms.Form): search = forms.CharField(label=_('Search String')) keywords = forms.ModelMultipleChoiceField( - queryset=Keyword.objects.all().order_by('id'), + queryset=Keyword.objects.none().order_by('id'), required=False, widget=MultiSelectWidget ) @@ -280,6 +264,9 @@ class ImportRecipeForm(forms.ModelForm): 'file_uid': _('File ID'), } widgets = {'keywords': MultiSelectWidget} + field_classes = { + 'keywords': SafeModelChoiceField, + } class RecipeBookForm(forms.ModelForm): @@ -287,6 +274,9 @@ class RecipeBookForm(forms.ModelForm): model = RecipeBook fields = ('name', 'icon', 'description', 'shared') widgets = {'icon': EmojiPickerTextInput, 'shared': MultiSelectWidget} + field_classes = { + 'shared': SafeModelMultipleChoiceField, + } class MealPlanForm(forms.ModelForm): @@ -318,6 +308,11 @@ class MealPlanForm(forms.ModelForm): 'date': DateWidget, 'shared': MultiSelectWidget } + field_classes = { + 'recipe': SafeModelChoiceField, + 'meal_type': SafeModelChoiceField, + 'shared': SafeModelMultipleChoiceField, + } class InviteLinkForm(forms.ModelForm): diff --git a/cookbook/models.py b/cookbook/models.py index 81eb6ec0..bedc619a 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -10,6 +10,7 @@ from django.db import models from django.utils import timezone from django.utils.translation import gettext as _ from django_random_queryset import RandomManager +from django_scopes import ScopedManager from recipes.settings import (COMMENT_PREF_DEFAULT, FRACTION_PREF_DEFAULT, STICKY_NAV_PREF_DEFAULT) @@ -107,6 +108,9 @@ class UserPreference(models.Model): shopping_auto_sync = models.IntegerField(default=5) sticky_navbar = models.BooleanField(default=STICKY_NAV_PREF_DEFAULT) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return str(self.user) @@ -128,6 +132,9 @@ class Storage(models.Model): path = models.CharField(blank=True, default='', max_length=256) created_by = models.ForeignKey(User, on_delete=models.PROTECT) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return self.name @@ -140,6 +147,9 @@ class Sync(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return self.path @@ -148,6 +158,9 @@ class SupermarketCategory(models.Model): name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return self.name @@ -157,6 +170,9 @@ class Supermarket(models.Model): description = models.TextField(blank=True, null=True) categories = models.ManyToManyField(SupermarketCategory, through='SupermarketCategoryRelation') + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return self.name @@ -166,6 +182,8 @@ class SupermarketCategoryRelation(models.Model): category = models.ForeignKey(SupermarketCategory, on_delete=models.CASCADE, related_name='category_to_supermarket') order = models.IntegerField(default=0) + objects = ScopedManager(space='supermarket__space') + class Meta: ordering = ('order',) @@ -176,6 +194,9 @@ class SyncLog(models.Model): msg = models.TextField(default="") created_at = models.DateTimeField(auto_now_add=True) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return f"{self.created_at}:{self.sync} - {self.status}" @@ -187,6 +208,9 @@ class Keyword(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): if self.icon: return f"{self.icon} {self.name}" @@ -198,6 +222,9 @@ class Unit(models.Model): name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return self.name @@ -209,6 +236,9 @@ class Food(models.Model): ignore_shopping = models.BooleanField(default=False) description = models.TextField(default='', blank=True) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return self.name @@ -226,6 +256,8 @@ class Ingredient(models.Model): no_amount = models.BooleanField(default=False) order = models.IntegerField(default=0) + objects = ScopedManager(space='step__recipe__space') + def __str__(self): return str(self.amount) + ' ' + str(self.unit) + ' ' + str(self.food) @@ -249,6 +281,8 @@ class Step(models.Model): order = models.IntegerField(default=0) show_as_header = models.BooleanField(default=True) + objects = ScopedManager(space='recipe__space') + def get_instruction_render(self): from cookbook.helper.template_helper import render_instructions return render_instructions(self) @@ -268,6 +302,8 @@ class NutritionInformation(models.Model): max_length=512, default="", null=True, blank=True ) + objects = ScopedManager(space='recipe__space') + def __str__(self): return 'Nutrition' @@ -297,7 +333,8 @@ class Recipe(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) - objects = RandomManager() + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') def __str__(self): return self.name @@ -310,6 +347,8 @@ class Comment(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) + objects = ScopedManager(space='recipe__space') + def __str__(self): return self.text @@ -321,6 +360,9 @@ class RecipeImport(models.Model): file_path = models.CharField(max_length=512, default="") created_at = models.DateTimeField(auto_now_add=True) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return self.name @@ -334,6 +376,9 @@ class RecipeBook(models.Model): ) created_by = models.ForeignKey(User, on_delete=models.CASCADE) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return self.name @@ -342,6 +387,9 @@ class RecipeBookEntry(models.Model): recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE) book = models.ForeignKey(RecipeBook, on_delete=models.CASCADE) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return self.recipe.name @@ -360,6 +408,9 @@ class MealType(models.Model): order = models.IntegerField(default=0) created_by = models.ForeignKey(User, on_delete=models.CASCADE) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return self.name @@ -378,6 +429,9 @@ class MealPlan(models.Model): note = models.TextField(blank=True) date = models.DateField() + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def get_label(self): if self.title: return self.title @@ -396,6 +450,9 @@ class ShoppingListRecipe(models.Model): ) servings = models.DecimalField(default=1, max_digits=8, decimal_places=4) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return f'Shopping list recipe {self.id} - {self.recipe}' @@ -414,6 +471,9 @@ class ShoppingListEntry(models.Model): order = models.IntegerField(default=0) checked = models.BooleanField(default=False) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return f'Shopping list entry {self.id}' @@ -435,6 +495,9 @@ class ShoppingList(models.Model): created_by = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return f'Shopping list {self.id}' @@ -445,6 +508,9 @@ class ShareLink(models.Model): created_by = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return f'{self.recipe} - {self.uuid}' @@ -464,6 +530,9 @@ class InviteLink(models.Model): created_by = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return f'{self.uuid}' @@ -475,6 +544,9 @@ class CookLog(models.Model): rating = models.IntegerField(null=True) servings = models.IntegerField(default=0) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return self.recipe.name @@ -484,5 +556,8 @@ class ViewLog(models.Model): created_by = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) + space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + objects = ScopedManager(space='space') + def __str__(self): return self.recipe.name diff --git a/cookbook/urls.py b/cookbook/urls.py index ba9a8d75..08b3a834 100644 --- a/cookbook/urls.py +++ b/cookbook/urls.py @@ -89,7 +89,6 @@ urlpatterns = [ path('api/log_cooking//', api.log_cooking, name='api_log_cooking'), path('api/plan-ical///', api.get_plan_ical, name='api_get_plan_ical'), path('api/recipe-from-url/', api.recipe_from_url, name='api_recipe_from_url'), - path('api/backup/', api.get_backup, name='api_backup'), path('api/ingredient-from-string/', api.ingredient_from_string, name='api_ingredient_from_string'), path('dal/keyword/', dal.KeywordAutocomplete.as_view(), name='dal_keyword'), diff --git a/cookbook/views/api.py b/cookbook/views/api.py index ab480f31..eb111b50 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -59,7 +59,7 @@ from recipes.settings import DEMO class StandardFilterMixin(ViewSetMixin): def get_queryset(self): - queryset = self.queryset + queryset = self.queryset.filter(userpreference__space=self.request.user.userpreference.space) query = self.request.query_params.get('query', None) if query is not None: queryset = queryset.filter(name__icontains=query) @@ -90,13 +90,13 @@ class UserNameViewSet(viewsets.ReadOnlyModelViewSet): - **filter_list**: array of user id's to get names for """ - queryset = User.objects.all() + queryset = User.objects serializer_class = UserNameSerializer permission_classes = [CustomIsGuest] http_method_names = ['get'] def get_queryset(self): - queryset = self.queryset + queryset = self.queryset.filter(userpreference__space=self.request.user.userpreference.space) try: filter_list = self.request.query_params.get('filter_list', None) if filter_list is not None: @@ -110,7 +110,7 @@ class UserNameViewSet(viewsets.ReadOnlyModelViewSet): class UserPreferenceViewSet(viewsets.ModelViewSet): - queryset = UserPreference.objects.all() + queryset = UserPreference.objects serializer_class = UserPreferenceSerializer permission_classes = [CustomIsOwner, ] @@ -120,35 +120,45 @@ class UserPreferenceViewSet(viewsets.ModelViewSet): serializer.save(user=self.request.user) def get_queryset(self): - if self.request.user.is_superuser: - return self.queryset return self.queryset.filter(user=self.request.user) class StorageViewSet(viewsets.ModelViewSet): # TODO handle delete protect error and adjust test - queryset = Storage.objects.all() + queryset = Storage.objects serializer_class = StorageSerializer permission_classes = [CustomIsAdmin, ] + def get_queryset(self): + return self.queryset.filter(space=self.request.user.userpreference.space) + class SyncViewSet(viewsets.ModelViewSet): - queryset = Sync.objects.all() + queryset = Sync.objects serializer_class = SyncSerializer permission_classes = [CustomIsAdmin, ] + def get_queryset(self): + return self.queryset.filter(space=self.request.user.userpreference.space) + class SyncLogViewSet(viewsets.ReadOnlyModelViewSet): - queryset = SyncLog.objects.all() + queryset = SyncLog.objects serializer_class = SyncLogSerializer permission_classes = [CustomIsAdmin, ] + def get_queryset(self): + return self.queryset.filter(space=self.request.user.userpreference.space) + class SupermarketViewSet(viewsets.ModelViewSet, StandardFilterMixin): - queryset = Supermarket.objects.all() + queryset = Supermarket.objects serializer_class = SupermarketSerializer permission_classes = [CustomIsUser] + def get_queryset(self): + return self.queryset.filter(space=self.request.user.userpreference.space) + class KeywordViewSet(viewsets.ModelViewSet, StandardFilterMixin): """ @@ -159,44 +169,48 @@ class KeywordViewSet(viewsets.ModelViewSet, StandardFilterMixin): in the keyword name (case in-sensitive) - **limit**: limits the amount of returned results """ - queryset = Keyword.objects.all() + queryset = Keyword.objects serializer_class = KeywordSerializer permission_classes = [CustomIsUser] + def get_queryset(self): + return self.queryset.filter(space=self.request.user.userpreference.space) + class UnitViewSet(viewsets.ModelViewSet, StandardFilterMixin): - queryset = Unit.objects.all() + queryset = Unit.objects serializer_class = UnitSerializer permission_classes = [CustomIsUser] + def get_queryset(self): + return self.queryset.filter(space=self.request.user.userpreference.space) + class FoodViewSet(viewsets.ModelViewSet, StandardFilterMixin): - queryset = Food.objects.all() + queryset = Food.objects serializer_class = FoodSerializer permission_classes = [CustomIsUser] + def get_queryset(self): + return self.queryset.filter(space=self.request.user.userpreference.space) + class RecipeBookViewSet(viewsets.ModelViewSet, StandardFilterMixin): - queryset = RecipeBook.objects.all() + queryset = RecipeBook.objects serializer_class = RecipeBookSerializer permission_classes = [CustomIsOwner] def get_queryset(self): - self.queryset = super(RecipeBookViewSet, self).get_queryset() - if self.request.user.is_superuser: - return self.queryset - return self.queryset.filter(created_by=self.request.user) + return self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space) class RecipeBookEntryViewSet(viewsets.ModelViewSet, viewsets.GenericViewSet): - queryset = RecipeBookEntry.objects.all() + queryset = RecipeBookEntry.objects serializer_class = RecipeBookEntrySerializer permission_classes = [CustomIsOwner] def get_queryset(self): - if self.request.user.is_superuser: - return self.queryset - return self.queryset.filter(created_by=self.request.user) + return self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space) class MealPlanViewSet(viewsets.ModelViewSet): @@ -208,15 +222,15 @@ class MealPlanViewSet(viewsets.ModelViewSet): - **to_date**: filter upward to (inclusive) certain date """ - queryset = MealPlan.objects.all() + queryset = MealPlan.objects serializer_class = MealPlanSerializer permission_classes = [CustomIsOwner] def get_queryset(self): - queryset = MealPlan.objects.filter( + queryset = self.queryset.filter( Q(created_by=self.request.user) | Q(shared=self.request.user) - ).distinct().all() + ).filter(space=self.request.user.userpreference.space).distinct().all() from_date = self.request.query_params.get('from_date', None) if from_date is not None: @@ -233,26 +247,32 @@ class MealTypeViewSet(viewsets.ModelViewSet): returns list of meal types created by the requesting user ordered by the order field. """ - queryset = MealType.objects.order_by('order').all() + queryset = MealType.objects serializer_class = MealTypeSerializer permission_classes = [CustomIsOwner] def get_queryset(self): - queryset = MealType.objects.order_by('order', 'id').filter(created_by=self.request.user).all() + queryset = self.queryset.order_by('order', 'id').filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all() return queryset class IngredientViewSet(viewsets.ModelViewSet): - queryset = Ingredient.objects.all() + queryset = Ingredient.objects serializer_class = IngredientSerializer permission_classes = [CustomIsUser] + def get_queryset(self): + return self.queryset.filter(step__recipe__space=self.request.user.userpreference.space) + class StepViewSet(viewsets.ModelViewSet): - queryset = Step.objects.all() + queryset = Step.objects serializer_class = StepSerializer permission_classes = [CustomIsUser] + def get_queryset(self): + return self.queryset.filter(recipe__space=self.request.user.userpreference.space) + class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin): """ @@ -263,18 +283,19 @@ class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin): in the recipe name (case in-sensitive) - **limit**: limits the amount of returned results """ - queryset = Recipe.objects.all() + queryset = Recipe.objects serializer_class = RecipeSerializer # TODO split read and write permission for meal plan guest permission_classes = [CustomIsShare | CustomIsGuest] def get_queryset(self): + queryset = self.queryset.filter(space=self.request.user.userpreference.space) internal = self.request.query_params.get('internal', None) if internal: - self.queryset = self.queryset.filter(internal=True) + queryset = queryset.filter(internal=True) - return super().get_queryset() + return queryset # TODO write extensive tests for permissions @@ -317,34 +338,32 @@ class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin): class ShoppingListRecipeViewSet(viewsets.ModelViewSet): - queryset = ShoppingListRecipe.objects.all() + queryset = ShoppingListRecipe.objects serializer_class = ShoppingListRecipeSerializer permission_classes = [CustomIsOwner, ] def get_queryset(self): - return self.queryset.filter(shoppinglist__created_by=self.request.user).all() + return self.queryset.filter(shoppinglist__created_by=self.request.user).filter(space=self.request.user.userpreference.space).all() class ShoppingListEntryViewSet(viewsets.ModelViewSet): - queryset = ShoppingListEntry.objects.all() + queryset = ShoppingListEntry.objects serializer_class = ShoppingListEntrySerializer permission_classes = [CustomIsOwner, ] def get_queryset(self): - return self.queryset.filter(shoppinglist__created_by=self.request.user).all() + return self.queryset.filter(shoppinglist__created_by=self.request.user).filter(space=self.request.user.userpreference.space).all() class ShoppingListViewSet(viewsets.ModelViewSet): - queryset = ShoppingList.objects.all() + queryset = ShoppingList.objects serializer_class = ShoppingListSerializer permission_classes = [CustomIsOwner | CustomIsShared] def get_queryset(self): - if self.request.user.is_superuser: - return self.queryset return self.queryset.filter( Q(created_by=self.request.user) | Q(shared=self.request.user) - ).all() + ).filter(space=self.request.user.userpreference.space).all() def get_serializer_class(self): autosync = self.request.query_params.get('autosync', None) @@ -354,21 +373,21 @@ class ShoppingListViewSet(viewsets.ModelViewSet): class ViewLogViewSet(viewsets.ModelViewSet): - queryset = ViewLog.objects.all() + queryset = ViewLog.objects serializer_class = ViewLogSerializer permission_classes = [CustomIsOwner] def get_queryset(self): - return CookLog.objects.filter(created_by=self.request.user).all()[:5] + return CookLog.objects.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all()[:5] class CookLogViewSet(viewsets.ModelViewSet): - queryset = CookLog.objects.all() + queryset = CookLog.objects serializer_class = CookLogSerializer permission_classes = [CustomIsOwner] def get_queryset(self): - queryset = CookLog.objects.filter(created_by=self.request.user).all()[:5] + queryset = CookLog.objects.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all()[:5] return queryset @@ -395,7 +414,7 @@ def update_recipe_links(recipe): @group_required('user') def get_external_file_link(request, recipe_id): - recipe = Recipe.objects.get(id=recipe_id) + recipe = Recipe.objects.filter(space=request.user.userpreference.space).get(id=recipe_id) if not recipe.link: update_recipe_links(recipe) @@ -404,7 +423,7 @@ def get_external_file_link(request, recipe_id): @group_required('guest') def get_recipe_file(request, recipe_id): - recipe = Recipe.objects.get(id=recipe_id) + recipe = Recipe.objects.filter(space=request.user.userpreference.space).get(id=recipe_id) if recipe.storage: return FileResponse(get_recipe_provider(recipe).get_file(recipe)) else: @@ -419,7 +438,7 @@ def sync_all(request): ) return redirect('index') - monitors = Sync.objects.filter(active=True) + monitors = Sync.objects.filter(active=True).filter(space=request.user.userpreference.space) error = False for monitor in monitors: @@ -471,7 +490,7 @@ def log_cooking(request, recipe_id): def get_plan_ical(request, from_date, to_date): queryset = MealPlan.objects.filter( Q(created_by=request.user) | Q(shared=request.user) - ).distinct().all() + ).filter(space=request.user.userpreference.space).distinct().all() if from_date is not None: queryset = queryset.filter(date__gte=from_date) @@ -525,22 +544,6 @@ def recipe_from_url(request): return get_from_html(response.text, url) -@group_required('admin') -def get_backup(request): - if not request.user.is_superuser: - return HttpResponse('', status=403) - - buf = io.StringIO() - management.call_command( - 'dumpdata', exclude=['contenttypes', 'auth'], stdout=buf - ) - - response = FileResponse(buf.getvalue()) - response["Content-Disposition"] = f'attachment; filename=backup{date_format(timezone.now(), format="SHORT_DATETIME_FORMAT", use_l10n=True)}.json' # noqa: E501 - - return response - - @group_required('user') def ingredient_from_string(request): text = request.POST['text'] diff --git a/cookbook/views/import_export.py b/cookbook/views/import_export.py index 02361c15..a77113d5 100644 --- a/cookbook/views/import_export.py +++ b/cookbook/views/import_export.py @@ -49,7 +49,7 @@ def import_recipe(request): @group_required('user') def export_recipe(request): if request.method == "POST": - form = ExportForm(request.POST) + form = ExportForm(request.POST, user=request.user) if form.is_valid(): try: integration = get_integration(request, form.cleaned_data['type']) @@ -58,11 +58,11 @@ def export_recipe(request): messages.add_message(request, messages.ERROR, _('Exporting is not implemented for this provider')) else: - form = ExportForm() + form = ExportForm(user=request.user) recipe = request.GET.get('r') if recipe: if re.match(r'^([0-9])+$', recipe): if recipe := Recipe.objects.filter(pk=int(recipe)).first(): - form = ExportForm(initial={'recipes': recipe}) + form = ExportForm(initial={'recipes': recipe}, user=request.user) return render(request, 'export.html', {'form': form}) diff --git a/requirements.txt b/requirements.txt index 61dce5f9..367b8317 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,3 +31,4 @@ Jinja2==2.11.3 django-webpack-loader==0.7.0 django-js-reverse==0.9.1 django-allauth==0.44.0 +django-scopes==1.2.0 \ No newline at end of file From 79f823cd628593dc3a76599c66b8bcc8fee556e8 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Fri, 19 Feb 2021 13:42:50 +0000 Subject: [PATCH 09/96] Apply translations in it translation completed for the source file '/cookbook/locale/en/LC_MESSAGES/django.po' on the 'it' language. --- cookbook/locale/it/LC_MESSAGES/django.po | 555 ++++++----------------- 1 file changed, 146 insertions(+), 409 deletions(-) diff --git a/cookbook/locale/it/LC_MESSAGES/django.po b/cookbook/locale/it/LC_MESSAGES/django.po index 6b829d94..ed945656 100644 --- a/cookbook/locale/it/LC_MESSAGES/django.po +++ b/cookbook/locale/it/LC_MESSAGES/django.po @@ -2,11 +2,11 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Alessandro Spallina , 2020 # Oliver Thomas Cervera , 2021 -# +# #, fuzzy msgid "" msgstr "" @@ -15,12 +15,11 @@ msgstr "" "POT-Creation-Date: 2021-02-09 18:01+0100\n" "PO-Revision-Date: 2020-06-02 19:28+0000\n" "Last-Translator: Oliver Thomas Cervera , 2021\n" -"Language-Team: Italian (https://www.transifex.com/django-recipes/" -"teams/110507/it/)\n" -"Language: it\n" +"Language-Team: Italian (https://www.transifex.com/django-recipes/teams/110507/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: .\cookbook\filters.py:22 .\cookbook\templates\base.html:87 @@ -35,8 +34,8 @@ msgid "" "Color of the top navigation bar. Not all colors work with all themes, just " "try them out!" msgstr "" -"Colore della barra di navigazione in alto. Non tutti i colori funzionano con " -"tutti i temi, provali e basta!" +"Colore della barra di navigazione in alto. Non tutti i colori funzionano con" +" tutti i temi, provali e basta!" #: .\cookbook\forms.py:45 msgid "Default Unit to be used when inserting a new ingredient into a recipe." @@ -81,15 +80,15 @@ msgid "" "mobile data. If lower than instance limit it is reset when saving." msgstr "" "L'impostazione su 0 disabiliterà la sincronizzazione automatica. Quando si " -"visualizza una lista della spesa, la lista viene aggiornata ogni tot secondi " -"impostati per sincronizzare le modifiche che qualcun altro potrebbe aver " -"fatto. Utile per gli acquisti con più persone, ma potrebbe utilizzare un po' " -"di dati mobili. Se inferiore al limite di istanza viene ripristinato durante " -"il salvataggio." +"visualizza una lista della spesa, la lista viene aggiornata ogni tot secondi" +" impostati per sincronizzare le modifiche che qualcun altro potrebbe aver " +"fatto. Utile per gli acquisti con più persone, ma potrebbe utilizzare un po'" +" di dati mobili. Se inferiore al limite di istanza viene ripristinato " +"durante il salvataggio." #: .\cookbook\forms.py:55 msgid "Makes the navbar stick to the top of the page." -msgstr "" +msgstr "Fissa la barra di navigazione nella parte superiore della pagina." #: .\cookbook\forms.py:71 msgid "" @@ -128,10 +127,8 @@ msgid "Storage UID" msgstr "UID di archiviazione" #: .\cookbook\forms.py:117 -#, fuzzy -#| msgid "Number of Days" msgid "Number of servings" -msgstr "Numero di giorni" +msgstr "Porzioni" #: .\cookbook\forms.py:128 msgid "" @@ -143,7 +140,7 @@ msgstr "" #: .\cookbook\forms.py:143 msgid "Default" -msgstr "" +msgstr "Predefinito" #: .\cookbook\forms.py:162 msgid "New Unit" @@ -192,11 +189,11 @@ msgstr "Lascia vuoto per nextcloud e inserisci l'api token per dropbox." #: .\cookbook\forms.py:244 msgid "" -"Leave empty for dropbox and enter only base url for nextcloud (/remote." -"php/webdav/ is added automatically)" +"Leave empty for dropbox and enter only base url for nextcloud " +"(/remote.php/webdav/ is added automatically)" msgstr "" -"Lascia vuoto per dropbox e inserisci solo l'url base per nextcloud (/" -"remote.php/webdav/ è aggiunto automaticamente)" +"Lascia vuoto per dropbox e inserisci solo l'url base per nextcloud " +"(/remote.php/webdav/ è aggiunto automaticamente)" #: .\cookbook\forms.py:263 msgid "Search String" @@ -219,11 +216,11 @@ msgstr "" #: .\cookbook\forms.py:313 #: .\cookbook\templates\forms\edit_internal_recipe.html:377 msgid "" -"You can use markdown to format this field. See the docs here" +"You can use markdown to format this field. See the docs here" msgstr "" -"Puoi usare markdown per formattare questo campo. Guarda la documentazione qui" +"Puoi usare markdown per formattare questo campo. Guarda la documentazione qui" #: .\cookbook\forms.py:328 msgid "A username is not required, if left blank the new user can choose one." @@ -258,8 +255,8 @@ msgstr "" #: .\cookbook\helper\recipe_url_import.py:53 msgid "" -"The requested site does not provide any recognized data format to import the " -"recipe from." +"The requested site does not provide any recognized data format to import the" +" recipe from." msgstr "" "Il sito richiesto non fornisce un formato di dati riconosciuto da cui " "importare la ricetta." @@ -273,6 +270,8 @@ msgid "" "Importer expected a .zip file. Did you choose the correct importer type for " "your data ?" msgstr "" +"La procedura di import necessita di un file .zip. Hai scelto il tipo di " +"importazione corretta per i tuoi dati?" #: .\cookbook\integration\safron.py:23 #: .\cookbook\templates\forms\edit_internal_recipe.html:65 @@ -282,10 +281,8 @@ msgid "Servings" msgstr "Porzioni" #: .\cookbook\integration\safron.py:25 -#, fuzzy -#| msgid "Waiting time ~" msgid "Waiting time" -msgstr "Tempo di Attesa ~" +msgstr "Tempo di attesa" #: .\cookbook\integration\safron.py:27 #: .\cookbook\templates\forms\edit_internal_recipe.html:59 @@ -300,7 +297,7 @@ msgstr "Ricettario" #: .\cookbook\integration\safron.py:31 msgid "Section" -msgstr "" +msgstr "Selezione" #: .\cookbook\migrations\0047_auto_20200602_1133.py:12 msgid "Breakfast" @@ -396,37 +393,35 @@ msgstr "Login" #: .\cookbook\templates\account\login.html:13 #: .\cookbook\templates\account\login.html:28 msgid "Sign In" -msgstr "" +msgstr "Accedi" #: .\cookbook\templates\account\login.html:38 msgid "Social Login" -msgstr "" +msgstr "Login con social network" #: .\cookbook\templates\account\login.html:39 msgid "You can use any of the following providers to sign in." -msgstr "" +msgstr "Puoi usare uno dei seguenti provider per accedere." #: .\cookbook\templates\account\logout.html:5 #: .\cookbook\templates\account\logout.html:9 #: .\cookbook\templates\account\logout.html:18 msgid "Sign Out" -msgstr "" +msgstr "Esci" #: .\cookbook\templates\account\logout.html:11 -#, fuzzy -#| msgid "Are you sure that you want to merge these two units?" msgid "Are you sure you want to sign out?" -msgstr "Sei sicuro di volere unire queste due unità di misura?" +msgstr "Sei sicuro di voler uscire?" #: .\cookbook\templates\account\password_reset.html:5 #: .\cookbook\templates\account\password_reset_done.html:5 msgid "Password Reset" -msgstr "" +msgstr "Recupero password" #: .\cookbook\templates\account\password_reset.html:9 #: .\cookbook\templates\account\password_reset_done.html:9 msgid "Password reset is not implemented for the time being!" -msgstr "" +msgstr "Il recupero della password non è stato ancora implementato!" #: .\cookbook\templates\account\signup.html:5 msgid "Register" @@ -540,8 +535,8 @@ msgstr "Modifica di massa per ricette" #: .\cookbook\templates\batch\edit.html:20 msgid "Add the specified keywords to all recipes containing a word" msgstr "" -"Aggiungi a tutte le ricette che contengono una determinata stringa le parole " -"chiave desiderate " +"Aggiungi a tutte le ricette che contengono una determinata stringa le parole" +" chiave desiderate " #: .\cookbook\templates\batch\monitor.html:6 .\cookbook\views\edit.py:66 msgid "Sync" @@ -556,8 +551,8 @@ msgid "" "On this Page you can manage all storage folder locations that should be " "monitored and synced." msgstr "" -"In questa pagina puoi gestire i percorsi delle cartelle di archiviazione che " -"devono essere monitorate e sincronizzate." +"In questa pagina puoi gestire i percorsi delle cartelle di archiviazione che" +" devono essere monitorate e sincronizzate." #: .\cookbook\templates\batch\monitor.html:16 msgid "The path must be in the following format" @@ -644,20 +639,16 @@ msgid "Waiting Time" msgstr "Tempo di Attesa" #: .\cookbook\templates\forms\edit_internal_recipe.html:68 -#, fuzzy -#| msgid "Servings" msgid "Servings Text" -msgstr "Porzioni" +msgstr "Nome delle porzioni" #: .\cookbook\templates\forms\edit_internal_recipe.html:79 msgid "Select Keywords" msgstr "Seleziona parole chiave" #: .\cookbook\templates\forms\edit_internal_recipe.html:93 -#, fuzzy -#| msgid "Nutrition" msgid "Description" -msgstr "Nutrienti" +msgstr "Descrizione" #: .\cookbook\templates\forms\edit_internal_recipe.html:108 msgid "Nutrition" @@ -773,7 +764,7 @@ msgstr "Abilita Quantità" #: .\cookbook\templates\forms\edit_internal_recipe.html:348 msgid "Copy Template Reference" -msgstr "" +msgstr "Copia riferimento template" #: .\cookbook\templates\forms\edit_internal_recipe.html:374 #: .\cookbook\templates\url_import.html:177 @@ -821,19 +812,14 @@ msgstr "Modifica Ingredienti" #: .\cookbook\templates\forms\ingredients.html:16 msgid "" "\n" -" The following form can be used if, accidentally, two (or more) units " -"or ingredients where created that should be\n" +" The following form can be used if, accidentally, two (or more) units or ingredients where created that should be\n" " the same.\n" -" It merges two units or ingredients and updates all recipes using " -"them.\n" +" It merges two units or ingredients and updates all recipes using them.\n" " " msgstr "" "\n" -" Questo modulo può essere utilizzato se, accidentalmente, sono stati " -"creati due (o più) unità di misura o ingredienti che dovrebbero essere lo " -"stesso. \n" -"Unisce due unità di misura o ingredienti e aggiorna tutte le ricette che li " -"utilizzano." +" Questo modulo può essere utilizzato se, accidentalmente, sono stati creati due (o più) unità di misura o ingredienti che dovrebbero essere lo stesso. \n" +"Unisce due unità di misura o ingredienti e aggiorna tutte le ricette che li utilizzano." #: .\cookbook\templates\forms\ingredients.html:24 #: .\cookbook\templates\stats.html:26 @@ -955,19 +941,15 @@ msgstr "Avviso di Sicurezza" #: .\cookbook\templates\include\storage_backend_warning.html:5 msgid "" "\n" -" The Password and Token field are stored as plain text " -"inside the database.\n" -" This is necessary because they are needed to make API requests, but " -"it also increases the risk of\n" +" The Password and Token field are stored as plain text inside the database.\n" +" This is necessary because they are needed to make API requests, but it also increases the risk of\n" " someone stealing it.
\n" -" To limit the possible damage tokens or accounts with limited access " -"can be used.\n" +" To limit the possible damage tokens or accounts with limited access can be used.\n" " " msgstr "" "\n" "I campi Password e Token sono salvati in chiaro nel database.\n" -"È necessario perché servono per fare richieste API, ma questo aumenta il " -"rischio che\n" +"È necessario perché servono per fare richieste API, ma questo aumenta il rischio che\n" "qualcuno possa impossessarsene.
\n" "Per liminare il danno puoi usare account con accesso limitato o i token." @@ -1012,29 +994,19 @@ msgstr "Informazioni su Markdown" #: .\cookbook\templates\markdown_info.html:14 msgid "" "\n" -" Markdown is lightweight markup language that can be used to format " -"plain text easily.\n" -" This site uses the Python Markdown library to\n" -" convert your text into nice looking HTML. Its full markdown " -"documentation can be found\n" -" here.\n" -" An incomplete but most likely sufficient documentation can be found " -"below.\n" +" Markdown is lightweight markup language that can be used to format plain text easily.\n" +" This site uses the Python Markdown library to\n" +" convert your text into nice looking HTML. Its full markdown documentation can be found\n" +" here.\n" +" An incomplete but most likely sufficient documentation can be found below.\n" " " msgstr "" "\n" -" Markdown è un linguaggio di markup molto leggero che può essere " -"utilizzato per formattare facilmente del testo.\n" -" Questo sito utilizza la libreria Python Markdown per\n" -" convertire il tuo testo in HTML formattato. È possibile trovare la " -"documentazione completa del markdown\n" -" qui.\n" -" Di seguito è possibile trovare una documentazione incompleta ma molto " -"probabilmente sufficiente." +" Markdown è un linguaggio di markup molto leggero che può essere utilizzato per formattare facilmente del testo.\n" +" Questo sito utilizza la libreria Python Markdown per\n" +" convertire il tuo testo in HTML formattato. È possibile trovare la documentazione completa del markdown\n" +" qui.\n" +" Di seguito è possibile trovare una documentazione incompleta ma molto probabilmente sufficiente." #: .\cookbook\templates\markdown_info.html:25 msgid "Headers" @@ -1134,19 +1106,15 @@ msgid "Tables" msgstr "Tabelle" #: .\cookbook\templates\markdown_info.html:153 -#, fuzzy -#| msgid "" -#| "Markdown tables are hard to create by hand. It is recommended to use a " -#| "table editor like this one." msgid "" -"Markdown tables are hard to create by hand. It is recommended to use a table " -"editor like this one." +"Markdown tables are hard to create by hand. It is recommended to use a table" +" editor like this one." msgstr "" -"Le tabelle in markdown sono difficili da creare a mano. È raccomandato " -"utilizzare un editor di tabelle come questo." +"Le tabelle in markdown sono difficili da creare a mano. Si raccomanda " +"l'utilizzo di un editor di come questo." #: .\cookbook\templates\markdown_info.html:155 #: .\cookbook\templates\markdown_info.html:157 @@ -1184,19 +1152,18 @@ msgstr "Note (opzionale)" #: .\cookbook\templates\meal_plan.html:143 msgid "" -"You can use markdown to format this field. See the docs here" +"You can use markdown to format this field. See the docs " +"here" msgstr "" -"Puoi usare markdown per formattare questo campo. Guarda la documentazione " -"qui" +"Puoi usare markdown per formattare questo campo. Guarda la documentazione qui" #: .\cookbook\templates\meal_plan.html:147 #: .\cookbook\templates\meal_plan.html:251 -#, fuzzy -#| msgid "Servings" msgid "Serving Count" -msgstr "Porzioni" +msgstr "Numero di porzioni" #: .\cookbook\templates\meal_plan.html:153 msgid "Create only note" @@ -1231,8 +1198,8 @@ msgstr "Correzione giorni feriali" #: .\cookbook\templates\meal_plan.html:209 msgid "" -"Number of days starting from the first day of the week to offset the default " -"view." +"Number of days starting from the first day of the week to offset the default" +" view." msgstr "" "Numero di giorni a partire dal primo giorno della settimana per correggere " "la visualizzazione predefinita." @@ -1274,98 +1241,40 @@ msgid "Meal Plan Help" msgstr "Aiuto per il piano alimentare" #: .\cookbook\templates\meal_plan.html:344 -#, fuzzy -#| msgid "" -#| "\n" -#| "

The meal plan module allows planning of " -#| "meals both with recipes or just notes.

\n" -#| "

Simply select a recipe from the list of " -#| "recently viewed recipes or search the one you\n" -#| " want and drag it to the desired plan " -#| "position. You can also add a note and a title and\n" -#| " then drag the recipe to create a plan " -#| "entry with a custom title and note. Creating only\n" -#| " Notes is possible by dragging the create " -#| "note box into the plan.

\n" -#| "

Click on a recipe in order to open the " -#| "detail view. Here you can also add it to the\n" -#| " shopping list. You can also add all " -#| "recipes of a day to the shopping list by\n" -#| " clicking the shopping cart at the top of " -#| "the table.

\n" -#| "

Since a common use case is to plan meals " -#| "together you can define\n" -#| " users you want to share your plan with in " -#| "the settings.\n" -#| "

\n" -#| "

You can also edit the types of meals you " -#| "want to plan. If you share your plan with\n" -#| " someone with\n" -#| " different meals, their meal types will " -#| "appear in your list as well. To prevent\n" -#| " duplicates (e.g. Other and Misc.)\n" -#| " name your meal types the same as the " -#| "users you share your meals with and they will be\n" -#| " merged.

\n" -#| " " msgid "" "\n" -"

The meal plan module allows planning of meals " -"both with recipes and notes.

\n" -"

Simply select a recipe from the list of " -"recently viewed recipes or search the one you\n" -" want and drag it to the desired plan " -"position. You can also add a note and a title and\n" -" then drag the recipe to create a plan entry " -"with a custom title and note. Creating only\n" -" Notes is possible by dragging the create " -"note box into the plan.

\n" -"

Click on a recipe in order to open the " -"detailed view. There you can also add it to the\n" -" shopping list. You can also add all recipes " -"of a day to the shopping list by\n" -" clicking the shopping cart at the top of the " -"table.

\n" -"

Since a common use case is to plan meals " -"together you can define\n" -" users you want to share your plan with in " -"the settings.\n" +"

The meal plan module allows planning of meals both with recipes and notes.

\n" +"

Simply select a recipe from the list of recently viewed recipes or search the one you\n" +" want and drag it to the desired plan position. You can also add a note and a title and\n" +" then drag the recipe to create a plan entry with a custom title and note. Creating only\n" +" Notes is possible by dragging the create note box into the plan.

\n" +"

Click on a recipe in order to open the detailed view. There you can also add it to the\n" +" shopping list. You can also add all recipes of a day to the shopping list by\n" +" clicking the shopping cart at the top of the table.

\n" +"

Since a common use case is to plan meals together you can define\n" +" users you want to share your plan with in the settings.\n" "

\n" -"

You can also edit the types of meals you want " -"to plan. If you share your plan with\n" +"

You can also edit the types of meals you want to plan. If you share your plan with\n" " someone with\n" -" different meals, their meal types will " -"appear in your list as well. To prevent\n" +" different meals, their meal types will appear in your list as well. To prevent\n" " duplicates (e.g. Other and Misc.)\n" -" name your meal types the same as the users " -"you share your meals with and they will be\n" +" name your meal types the same as the users you share your meals with and they will be\n" " merged.

\n" " " msgstr "" "\n" -"

Il modulo del piano alimentare consente di pianificare i pasti sia con " -"ricette che con semplici note.

\n" +"

Il modulo del piano alimentare consente di pianificare i pasti sia con ricette che con semplici note.

\n" "

Seleziona una ricetta dalla lista delle ricette recenti o cercane una,\n" -"quindi spostala sulla posizione desiderata. Puoi anche aggiungere una nota e " -"un titolo e\n" -"poi trascinare la ricetta per creare una voce nel piano con un titolo e una " -"nota personalizzata. Si possono anche creare\n" +"quindi spostala sulla posizione desiderata. Puoi anche aggiungere una nota e un titolo e\n" +"poi trascinare la ricetta per creare una voce nel piano con un titolo e una nota personalizzata. Si possono anche creare\n" "delle note trascinando la casella della nota nel piano.

\n" -"

Clicca su una ricetta per aprire la pagina dei dettagli. Qui potrai anche " -"aggiungerla alla lista della spesa. Puoi anche aggiungere tutte le ricette " -"di un giorno alla lista della spesa, basterà cliccare sul carrello sopra la " -"tabella.

\n" -"

Dato che è comune pianificare i pasti con qualcun altro, nelle " -"impostazioni puoi scegliere gli utenti con i quali condividere il tuo piano." -"

\n" -"

Puoi anche modificare i tipi di pasto che vuoi pianificare. Se condividi " -"il piano con\n" +"

Clicca su una ricetta per aprire la vista dettagliata. Qui potrai anche aggiungerla alla lista della spesa. Puoi anche aggiungere tutte le ricette di un giorno alla lista della spesa, basterà cliccare sul carrello sopra la tabella.

\n" +"

Dato che è comune pianificare i pasti con altre persone, nelle impostazioni puoi scegliere gli utenti con i quali condividere il tuo piano.

\n" +"

Puoi anche modificare i tipi di pasto che vuoi pianificare. Se condividi il piano con\n" "qualcuno\n" -"con pasti differenti, i loro tipi di pasto appariranno anche nella tua " -"lista. Per prevenire\n" +"con pasti differenti, i loro tipi di pasto appariranno anche nella tua lista. Per evitare\n" "duplicati (es. Altri e Varie)\n" -"dai nomi ai tuoi tipi di pasto uguali ai tuoi utenti in modo che verranno " -"uniti.

" +"dai nomi ai tuoi tipi di pasto uguali ai tuoi utenti in modo che verranno uniti.

" #: .\cookbook\templates\meal_plan_entry.html:6 msgid "Meal Plan View" @@ -1382,27 +1291,32 @@ msgstr "Altri pasti di questo giorno" #: .\cookbook\templates\no_groups_info.html:5 #: .\cookbook\templates\offline.html:6 msgid "Offline" -msgstr "" +msgstr "Non in linea" #: .\cookbook\templates\no_groups_info.html:12 msgid "No Permissions" -msgstr "" +msgstr "Nessun permesso" #: .\cookbook\templates\no_groups_info.html:15 msgid "" "You do not have any groups and therefor cannot use this application. Please " "contact your administrator." msgstr "" +"Non fai parte di un gruppo e questo non ti consente di usare l'applicazione." +" Contatta il tuo amministratore." #: .\cookbook\templates\offline.html:19 msgid "You are currently offline!" -msgstr "" +msgstr "Al momento sei offline!" #: .\cookbook\templates\offline.html:20 msgid "" "The recipes listed below are available for offline viewing because you have " "recently viewed them. Keep in mind that data might be outdated." msgstr "" +"Le ricette qui sotto sono disponibili per essere consultate quando sei " +"offline perché le hai aperte di recente. Ricorda che queste informazioni " +"potrebbero non essere aggiornate." #: .\cookbook\templates\recipe_view.html:21 .\cookbook\templates\stats.html:47 msgid "Comments" @@ -1447,7 +1361,7 @@ msgstr "Account" #: .\cookbook\templates\settings.html:38 msgid "Link social account" -msgstr "" +msgstr "Collega account social" #: .\cookbook\templates\settings.html:42 msgid "Language" @@ -1471,8 +1385,8 @@ msgstr "" #: .\cookbook\templates\settings.html:92 msgid "" -"Use the token as an Authorization header prefixed by the word token as shown " -"in the following examples:" +"Use the token as an Authorization header prefixed by the word token as shown" +" in the following examples:" msgstr "" "Usa il token come header Authorization preceduto dalla parola Token come " "negli esempi seguenti:" @@ -1509,13 +1423,11 @@ msgstr "Nessuna ricetta selezionata" #: .\cookbook\templates\shopping_list.html:145 msgid "Entry Mode" -msgstr "" +msgstr "Modalità di inserimento" #: .\cookbook\templates\shopping_list.html:153 -#, fuzzy -#| msgid "New Entry" msgid "Add Entry" -msgstr "Nuovo Campo" +msgstr "Aggiungi voce" #: .\cookbook\templates\shopping_list.html:168 msgid "Amount" @@ -1523,13 +1435,11 @@ msgstr "Quantità" #: .\cookbook\templates\shopping_list.html:224 msgid "Supermarket" -msgstr "" +msgstr "Supermercato" #: .\cookbook\templates\shopping_list.html:234 -#, fuzzy -#| msgid "Select User" msgid "Select Supermarket" -msgstr "Seleziona utente" +msgstr "Seleziona supermercato" #: .\cookbook\templates\shopping_list.html:258 msgid "Select User" @@ -1558,26 +1468,27 @@ msgstr "Si è verificato un errore durante la creazione di una risorsa!" #: .\cookbook\templates\socialaccount\connections.html:4 #: .\cookbook\templates\socialaccount\connections.html:7 msgid "Account Connections" -msgstr "" +msgstr "Collegamenti dell'account" #: .\cookbook\templates\socialaccount\connections.html:10 msgid "" "You can sign in to your account using any of the following third party\n" " accounts:" msgstr "" +"Puoi accedere al tuo account usando uno dei seguenti account di terze parti:" #: .\cookbook\templates\socialaccount\connections.html:36 msgid "Remove" -msgstr "" +msgstr "Rimuovi" #: .\cookbook\templates\socialaccount\connections.html:44 msgid "" "You currently have no social network accounts connected to this account." -msgstr "" +msgstr "Non hai account di social network collegati a questo account." #: .\cookbook\templates\socialaccount\connections.html:47 msgid "Add a 3rd Party Account" -msgstr "" +msgstr "Aggiungi un account di terze parti" #: .\cookbook\templates\stats.html:4 msgid "Stats" @@ -1630,18 +1541,14 @@ msgstr "Informazioni di sistema" #: .\cookbook\templates\system.html:51 msgid "" "\n" -" Django Recipes is an open source free software application. It can " -"be found on\n" +" Django Recipes is an open source free software application. It can be found on\n" " GitHub.\n" -" Changelogs can be found here.\n" +" Changelogs can be found here.\n" " " msgstr "" "\n" -"Django Recipes è una applicazione gratuita e open source. È disponibile su " -"GitHub.\n" -"Le ultime novità sono disponibili qui." +"Django Recipes è una applicazione gratuita e open source. È disponibile su GitHub.\n" +"Le ultime novità sono disponibili qui." #: .\cookbook\templates\system.html:65 msgid "Media Serving" @@ -1661,16 +1568,13 @@ msgstr "Ok" msgid "" "Serving media files directly using gunicorn/python is not recommend!\n" " Please follow the steps described\n" -" here to update\n" +" here to update\n" " your installation.\n" " " msgstr "" -"Erogare i file multimediali usando gunicorn/python non è raccomandato!\n" +"Erogare i file multimediali usando gunicorn/python non è raccomandato!\n" "Segui i passi descritti\n" -"qui " -"per aggiornare la tua installazione." +"qui per aggiornare la tua installazione." #: .\cookbook\templates\system.html:74 .\cookbook\templates\system.html:90 #: .\cookbook\templates\system.html:105 .\cookbook\templates\system.html:119 @@ -1684,18 +1588,14 @@ msgstr "Chiave segreta" #: .\cookbook\templates\system.html:83 msgid "" "\n" -" You do not have a SECRET_KEY configured in your " -".env file. Django defaulted to the\n" +" You do not have a SECRET_KEY configured in your .env file. Django defaulted to the\n" " standard key\n" -" provided with the installation which is publicly know and " -"insecure! Please set\n" -" SECRET_KEY int the .env configuration " -"file.\n" +" provided with the installation which is publicly know and insecure! Please set\n" +" SECRET_KEY int the .env configuration file.\n" " " msgstr "" "\n" -"Non hai inserito una SECRET_KEY nel file .env. " -"Django ha dovuto usare la chiave standard\n" +"Non hai inserito una SECRET_KEY nel file .env. Django ha dovuto usare la chiave standard\n" "dell'installazione che è pubblica e insicura! Sei pregato di aggiungere una\n" "SECRET_KEY nel file di configurazione .env." @@ -1706,16 +1606,13 @@ msgstr "Modalità di debug" #: .\cookbook\templates\system.html:99 msgid "" "\n" -" This application is still running in debug mode. This is most " -"likely not needed. Turn of debug mode by\n" +" This application is still running in debug mode. This is most likely not needed. Turn of debug mode by\n" " setting\n" -" DEBUG=0 int the .env configuration " -"file.\n" +" DEBUG=0 int the .env configuration file.\n" " " msgstr "" "\n" -"Questa applicazione è in esecuzione in modalità di debug. Probabilmente non " -"è necessario, spegni la modalità di debug \n" +"Questa applicazione è in esecuzione in modalità di debug. Probabilmente non è necessario, spegni la modalità di debug \n" "configurando\n" "DEBUG=0 nel file di configurazione.env." @@ -1730,14 +1627,12 @@ msgstr "Info" #: .\cookbook\templates\system.html:114 msgid "" "\n" -" This application is not running with a Postgres database " -"backend. This is ok but not recommended as some\n" +" This application is not running with a Postgres database backend. This is ok but not recommended as some\n" " features only work with postgres databases.\n" " " msgstr "" "\n" -"Questa applicazione non sta girando su un database Postgres. Non è " -"raccomandato perché alcune\n" +"Questa applicazione non sta girando su un database Postgres. Non è raccomandato perché alcune\n" "funzionalità sono disponibili solo con un database Posgres." #: .\cookbook\templates\url_import.html:5 @@ -1773,18 +1668,14 @@ msgstr "Info" #: .\cookbook\templates\url_import.html:235 msgid "" " Only websites containing ld+json or microdata information can currently\n" -" be imported. Most big recipe pages " -"support this. If you site cannot be imported but\n" +" be imported. Most big recipe pages support this. If you site cannot be imported but\n" " you think\n" -" it probably has some kind of structured " -"data feel free to post an example in the\n" +" it probably has some kind of structured data feel free to post an example in the\n" " github issues." msgstr "" -"Possono essere importati solo i siti che contengono informazioni Id+json o " -"microdata.\n" +"Possono essere importati solo i siti che contengono informazioni Id+json o microdata.\n" "I maggiori siti di ricette di solito sono supportati.\n" -"Se questo sito non può essere importato ma credi che abbia una qualche tipo " -"di struttura dati, puoi inviare un esempio nella sezione Issues su GitHub." +"Se questo sito non può essere importato ma credi che abbia una qualche tipo di struttura dati, puoi inviare un esempio nella sezione Issues su GitHub." #: .\cookbook\templates\url_import.html:243 msgid "Google ld+json Info" @@ -1808,7 +1699,7 @@ msgstr "La preferenza per l'utente fornito esiste già" #: .\cookbook\views\api.py:416 .\cookbook\views\views.py:265 msgid "This feature is not available in the demo version!" -msgstr "" +msgstr "Questa funzione non è disponibile nella versione demo!" #: .\cookbook\views\api.py:439 msgid "Sync successful!" @@ -1832,7 +1723,8 @@ msgstr "" #, python-format msgid "Batch edit done. %(count)d recipe was updated." msgid_plural "Batch edit done. %(count)d Recipes where updated." -msgstr[0] "Modifica di massa completata. %(count)d ricetta è stata aggiornata." +msgstr[0] "" +"Modifica di massa completata. %(count)d ricetta è stata aggiornata." msgstr[1] "" "Modifica di massa completata. %(count)d ricette sono state aggiornate." @@ -1901,7 +1793,7 @@ msgstr "Le unità sono state unite!" #: .\cookbook\views\edit.py:295 .\cookbook\views\edit.py:317 msgid "Cannot merge with the same object!" -msgstr "" +msgstr "Non è possibile unirlo con lo stesso oggetto!" #: .\cookbook\views\edit.py:311 msgid "Foods merged!" @@ -1909,11 +1801,11 @@ msgstr "Gli alimenti sono stati uniti!" #: .\cookbook\views\import_export.py:42 msgid "Importing is not implemented for this provider" -msgstr "" +msgstr "Questo provider non permette l'importazione" #: .\cookbook\views\import_export.py:58 msgid "Exporting is not implemented for this provider" -msgstr "" +msgstr "Questo provider non permette l'esportazione" #: .\cookbook\views\lists.py:42 msgid "Import Log" @@ -1945,7 +1837,7 @@ msgstr "Commento salvato!" #: .\cookbook\views\views.py:152 msgid "This recipe is already linked to the book!" -msgstr "" +msgstr "Questa ricetta è già collegata al libro!" #: .\cookbook\views\views.py:158 msgid "Bookmark saved!" @@ -1954,8 +1846,8 @@ msgstr "Preferito salvato!" #: .\cookbook\views\views.py:380 msgid "" "The setup page can only be used to create the first user! If you have " -"forgotten your superuser credentials please consult the django documentation " -"on how to reset passwords." +"forgotten your superuser credentials please consult the django documentation" +" on how to reset passwords." msgstr "" "La pagina di configurazione può essere usata solo per creare il primo " "utente! Se hai dimenticato le credenziali del tuo super utente controlla la " @@ -1976,158 +1868,3 @@ msgstr "È stato fornito un link di invito non valido!" #: .\cookbook\views\views.py:470 msgid "Invite Link not valid or already used!" msgstr "Il link di invito non è valido o è stato già usato!" - -#~ msgid "Export Base64 encoded image?" -#~ msgstr "Esportare immagini codificate in Base64?" - -#~ msgid "Download export directly or show on page?" -#~ msgstr "Scaricare l'esportazione direttamente o mostrare sulla pagina?" - -#~ msgid "Simply paste a JSON export into this textarea and click import." -#~ msgstr "" -#~ "Semplicemente incolla un'esportazione JSON in questa area di testo e " -#~ "clicca su importa." - -#~ msgid "Scaling factor for recipe." -#~ msgstr "Fattore di ridimensionamento per le ricette." - -#~ msgid "Exported Recipe" -#~ msgstr "Ricette Esportate" - -#~ msgid "Copy to clipboard" -#~ msgstr "Copia negli appunti" - -#~ msgid "Copied!" -#~ msgstr "Copiato!" - -#~ msgid "Copy list to clipboard" -#~ msgstr "Copia la lista negli appunti" - -#~ msgid "Error" -#~ msgstr "Errore" - -#~ msgid "There was an error loading the recipe!" -#~ msgstr "Si è verificato un errore durante il caricamento della ricetta!" - -#~ msgid "Updated" -#~ msgstr "Caricato" - -#~ msgid "Changes saved successfully!" -#~ msgstr "Cambiamenti salvati con successo!" - -#~ msgid "There was an error updating the recipe!" -#~ msgstr "Si è verificato un errore durante l'aggiornamento della ricetta!" - -#~ msgid "Are you sure that you want to delete this ingredient?" -#~ msgstr "Sei sicuro di voler eliminare questo ingrediente?" - -#~ msgid "Are you sure that you want to delete this step?" -#~ msgstr "Sei sicuro di voler eliminare questo step?" - -#~ msgid "There was an error loading a resource!" -#~ msgstr "Si è verificato un errore durante il caricamento di una risorsa!" - -#~ msgid "Recipe Multiplier" -#~ msgstr "Moltiplicatore di Ricetta" - -#~ msgid "" -#~ "When deleting a meal type all entries using that type will be deleted as " -#~ "well. Deletion will apply when configuration is saved. Do you want to " -#~ "proceed?" -#~ msgstr "" -#~ "Quando elimi un tipo di pasto tutte le voci che usano quel tipo verranno " -#~ "eliminate. L'eliminazione avviene quando la configurazione viene salvata. " -#~ "Vuoi procedere?" - -#~ msgid "Add to Book" -#~ msgstr "Aggiungi a libro" - -#~ msgid "Add to Plan" -#~ msgstr "Aggiungi a piano" - -#~ msgid "Print" -#~ msgstr "Stampa" - -#~ msgid "Share" -#~ msgstr "Condividi" - -#~ msgid "in" -#~ msgstr "in" - -#~ msgid "Preparation time ~" -#~ msgstr "Tempo di preparazione ~" - -#~ msgid "Minutes" -#~ msgstr "Minuti" - -#~ msgid "View external recipe" -#~ msgstr "Mostra ricetta esterna" - -#~ msgid "External recipe image" -#~ msgstr "Immagine ricetta esterna" - -#~ msgid "External recipe" -#~ msgstr "Ricetta Esterna" - -#~ msgid "" -#~ "\n" -#~ " This is an external recipe, which " -#~ "means you can only view it by opening the link\n" -#~ " above.\n" -#~ " You can convert this recipe to a " -#~ "fancy recipe by pressing the convert button. The\n" -#~ " original\n" -#~ " file\n" -#~ " will still be accessible.\n" -#~ " " -#~ msgstr "" -#~ "\n" -#~ "Questa è una ricetta esterna, che significa puoi solo aprirla con il " -#~ "link \n" -#~ "qui sopra.\n" -#~ "Puoi convertire questa ricetta ad una più bella cliccando il tasto " -#~ "Converti.\n" -#~ "Il\n" -#~ "file \n" -#~ "originale\n" -#~ "sarà sempre accessibile." - -#~ msgid "Convert now!" -#~ msgstr "Converti ora!" - -#~ msgid "Your username and password didn't match. Please try again." -#~ msgstr "" -#~ "La combinazione inserita di username e password non è valida. Riprova." - -#~ msgid "There was an error updating a resource!" -#~ msgstr "Si è verificato un errore durante l'aggiornamento di una risorsa!" - -#~ msgid "Object created successfully!" -#~ msgstr "Oggetto creato con successo!" - -#~ msgid "Please enter a valid food" -#~ msgstr "Inserisci un alimento valido" - -#~ msgid "Already importing the selected recipe, please wait!" -#~ msgstr "L'importazione della ricetta selezionata è già in corso, attendere!" - -#~ msgid "An error occurred while trying to import this recipe!" -#~ msgstr "" -#~ "Si è verificato un errore durante il tentativo d'importazione di questa " -#~ "ricetta!" - -#~ msgid "Recipe imported successfully!" -#~ msgstr "Ricetta importata con successo!" - -#~ msgid "Something went wrong during the import!" -#~ msgstr "Qualcosa è andato storto durante l'importazione!" - -#~ msgid "Could not parse the supplied JSON!" -#~ msgstr "Impossibile analizzare il codice JSON!" - -#~ msgid "" -#~ "External recipes cannot be exported, please share the file directly or " -#~ "select an internal recipe." -#~ msgstr "" -#~ "Le ricette esterne non possono esportate, condividi direttamente il file " -#~ "oppure seleziona una ricetta interna." From fb58d350298d00be4e0b9cda616a029ae0d94237 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Fri, 19 Feb 2021 15:50:55 +0100 Subject: [PATCH 10/96] space stuff partially working --- cookbook/helper/scope_middleware.py | 15 ++ .../migrations/0108_auto_20210219_1410.py | 146 +++++++++++++++++ cookbook/models.py | 45 +++--- cookbook/templates/system.html | 17 -- cookbook/views/lists.py | 42 ++--- cookbook/views/new.py | 52 +++---- cookbook/views/views.py | 147 ++++++------------ recipes/settings.py | 1 + 8 files changed, 274 insertions(+), 191 deletions(-) create mode 100644 cookbook/helper/scope_middleware.py create mode 100644 cookbook/migrations/0108_auto_20210219_1410.py diff --git a/cookbook/helper/scope_middleware.py b/cookbook/helper/scope_middleware.py new file mode 100644 index 00000000..595a5f91 --- /dev/null +++ b/cookbook/helper/scope_middleware.py @@ -0,0 +1,15 @@ +from django_scopes import scope + + +class ScopeMiddleware: + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + if request.user.is_authenticated: + request.space = request.user.userpreference.space + + with scope(space=request.space): + return self.get_response(request) + else: + return self.get_response(request) diff --git a/cookbook/migrations/0108_auto_20210219_1410.py b/cookbook/migrations/0108_auto_20210219_1410.py new file mode 100644 index 00000000..b71d3fc6 --- /dev/null +++ b/cookbook/migrations/0108_auto_20210219_1410.py @@ -0,0 +1,146 @@ +# Generated by Django 3.1.6 on 2021-02-19 13:10 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0107_auto_20210128_1535'), + ] + + operations = [ + migrations.AddField( + model_name='cooklog', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='food', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='invitelink', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='keyword', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='mealplan', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='mealtype', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='recipe', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='recipebook', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='recipebookentry', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='recipeimport', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='sharelink', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='shoppinglist', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='shoppinglistentry', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='shoppinglistrecipe', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='storage', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='supermarket', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='supermarketcategory', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='sync', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='synclog', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='unit', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='userpreference', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + migrations.AddField( + model_name='viewlog', + name='space', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + preserve_default=False, + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index bedc619a..fd6ca6ce 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -108,7 +108,7 @@ class UserPreference(models.Model): shopping_auto_sync = models.IntegerField(default=5) sticky_navbar = models.BooleanField(default=STICKY_NAV_PREF_DEFAULT) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -132,7 +132,7 @@ class Storage(models.Model): path = models.CharField(blank=True, default='', max_length=256) created_by = models.ForeignKey(User, on_delete=models.PROTECT) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -147,7 +147,7 @@ class Sync(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -158,7 +158,7 @@ class SupermarketCategory(models.Model): name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -170,7 +170,7 @@ class Supermarket(models.Model): description = models.TextField(blank=True, null=True) categories = models.ManyToManyField(SupermarketCategory, through='SupermarketCategoryRelation') - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -194,7 +194,7 @@ class SyncLog(models.Model): msg = models.TextField(default="") created_at = models.DateTimeField(auto_now_add=True) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -208,7 +208,7 @@ class Keyword(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -222,7 +222,7 @@ class Unit(models.Model): name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -236,7 +236,7 @@ class Food(models.Model): ignore_shopping = models.BooleanField(default=False) description = models.TextField(default='', blank=True) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -333,7 +333,7 @@ class Recipe(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -360,7 +360,7 @@ class RecipeImport(models.Model): file_path = models.CharField(max_length=512, default="") created_at = models.DateTimeField(auto_now_add=True) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -376,7 +376,7 @@ class RecipeBook(models.Model): ) created_by = models.ForeignKey(User, on_delete=models.CASCADE) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -387,8 +387,7 @@ class RecipeBookEntry(models.Model): recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE) book = models.ForeignKey(RecipeBook, on_delete=models.CASCADE) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) - objects = ScopedManager(space='space') + objects = ScopedManager(space='book__space') def __str__(self): return self.recipe.name @@ -408,7 +407,7 @@ class MealType(models.Model): order = models.IntegerField(default=0) created_by = models.ForeignKey(User, on_delete=models.CASCADE) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -429,7 +428,7 @@ class MealPlan(models.Model): note = models.TextField(blank=True) date = models.DateField() - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def get_label(self): @@ -450,7 +449,7 @@ class ShoppingListRecipe(models.Model): ) servings = models.DecimalField(default=1, max_digits=8, decimal_places=4) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -471,7 +470,7 @@ class ShoppingListEntry(models.Model): order = models.IntegerField(default=0) checked = models.BooleanField(default=False) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -495,7 +494,7 @@ class ShoppingList(models.Model): created_by = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -508,7 +507,7 @@ class ShareLink(models.Model): created_by = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -530,7 +529,7 @@ class InviteLink(models.Model): created_by = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -544,7 +543,7 @@ class CookLog(models.Model): rating = models.IntegerField(null=True) servings = models.IntegerField(default=0) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): @@ -556,7 +555,7 @@ class ViewLog(models.Model): created_by = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) - space = models.ForeignKey(Space, blank=True, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): diff --git a/cookbook/templates/system.html b/cookbook/templates/system.html index 8bf1b2b7..442e44ae 100644 --- a/cookbook/templates/system.html +++ b/cookbook/templates/system.html @@ -22,23 +22,6 @@ {% trans 'Show Links' %} -
diff --git a/cookbook/views/lists.py b/cookbook/views/lists.py index 14198379..7cfcb229 100644 --- a/cookbook/views/lists.py +++ b/cookbook/views/lists.py @@ -17,7 +17,7 @@ from cookbook.tables import (ImportLogTable, IngredientTable, InviteLinkTable, @group_required('user') def keyword(request): - table = KeywordTable(Keyword.objects.all()) + table = KeywordTable(Keyword.objects.filter(space=request.space).all()) RequestConfig(request, paginate={'per_page': 25}).configure(table) return render( @@ -30,7 +30,7 @@ def keyword(request): @group_required('admin') def sync_log(request): table = ImportLogTable( - SyncLog.objects.all().order_by('-created_at') + SyncLog.objects.filter(space=request.space).all().order_by('-created_at') ) RequestConfig(request, paginate={'per_page': 25}).configure(table) @@ -43,7 +43,7 @@ def sync_log(request): @group_required('user') def recipe_import(request): - table = RecipeImportTable(RecipeImport.objects.all()) + table = RecipeImportTable(RecipeImport.objects.filter(space=request.space).all()) RequestConfig(request, paginate={'per_page': 25}).configure(table) @@ -56,10 +56,7 @@ def recipe_import(request): @group_required('user') def food(request): - f = IngredientFilter( - request.GET, - queryset=Food.objects.all().order_by('pk') - ) + f = IngredientFilter(request.GET, queryset=Food.objects.filter(space=request.space).all().order_by('pk')) table = IngredientTable(f.qs) RequestConfig(request, paginate={'per_page': 25}).configure(table) @@ -73,12 +70,10 @@ def food(request): @group_required('user') def shopping_list(request): - f = ShoppingListFilter( - request.GET, - queryset=ShoppingList.objects.filter( - Q(created_by=request.user) | - Q(shared=request.user) - ).all().order_by('finished', 'created_at')) + f = ShoppingListFilter(request.GET, queryset=ShoppingList.objects.filter( + Q(created_by=request.user) | + Q(shared=request.user), space=request.space + ).all().order_by('finished', 'created_at')) table = ShoppingListTable(f.qs) RequestConfig(request, paginate={'per_page': 25}).configure(table) @@ -97,7 +92,7 @@ def shopping_list(request): @group_required('admin') def storage(request): - table = StorageTable(Storage.objects.all()) + table = StorageTable(Storage.objects.filter(space=request.space).all()) RequestConfig(request, paginate={'per_page': 25}).configure(table) return render( @@ -113,18 +108,11 @@ def storage(request): @group_required('admin') def invite_link(request): - table = InviteLinkTable( - InviteLink.objects.filter( - valid_until__gte=datetime.today(), used_by=None - ).all()) + table = InviteLinkTable(InviteLink.objects.filter(valid_until__gte=datetime.today(), used_by=None, space=request.space).all()) RequestConfig(request, paginate={'per_page': 25}).configure(table) - return render( - request, - 'generic/list_template.html', - { - 'title': _("Invite Links"), - 'table': table, - 'create_url': 'new_invite_link' - } - ) + return render(request, 'generic/list_template.html', { + 'title': _("Invite Links"), + 'table': table, + 'create_url': 'new_invite_link' + }) diff --git a/cookbook/views/new.py b/cookbook/views/new.py index 877c2602..bdc2bac7 100644 --- a/cookbook/views/new.py +++ b/cookbook/views/new.py @@ -25,12 +25,11 @@ class RecipeCreate(GroupRequiredMixin, CreateView): def form_valid(self, form): obj = form.save(commit=False) obj.created_by = self.request.user + obj.space = self.request.space obj.internal = True obj.save() obj.steps.add(Step.objects.create()) - return HttpResponseRedirect( - reverse('edit_recipe', kwargs={'pk': obj.pk}) - ) + return HttpResponseRedirect(reverse('edit_recipe', kwargs={'pk': obj.pk})) def get_success_url(self): return reverse('edit_recipe', kwargs={'pk': self.object.pk}) @@ -43,11 +42,9 @@ class RecipeCreate(GroupRequiredMixin, CreateView): @group_required('user') def share_link(request, pk): - recipe = get_object_or_404(Recipe, pk=pk) - link = ShareLink.objects.create(recipe=recipe, created_by=request.user) - return HttpResponseRedirect( - reverse('view_recipe', kwargs={'pk': pk, 'share': link.uuid}) - ) + recipe = get_object_or_404(Recipe, pk=pk, space=request.space) + link = ShareLink.objects.create(recipe=recipe, created_by=request.user, space=request.space) + return HttpResponseRedirect(reverse('view_recipe', kwargs={'pk': pk, 'share': link.uuid})) class KeywordCreate(GroupRequiredMixin, CreateView): @@ -57,6 +54,12 @@ class KeywordCreate(GroupRequiredMixin, CreateView): form_class = KeywordForm success_url = reverse_lazy('list_keyword') + def form_valid(self, form): + obj = form.save(commit=False) + obj.space = self.request.space + obj.save() + return HttpResponseRedirect(reverse('edit_keyword', kwargs={'pk': obj.pk})) + def get_context_data(self, **kwargs): context = super(KeywordCreate, self).get_context_data(**kwargs) context['title'] = _("Keyword") @@ -73,10 +76,9 @@ class StorageCreate(GroupRequiredMixin, CreateView): def form_valid(self, form): obj = form.save(commit=False) obj.created_by = self.request.user + obj.space = self.request.space obj.save() - return HttpResponseRedirect( - reverse('edit_storage', kwargs={'pk': obj.pk}) - ) + return HttpResponseRedirect(reverse('edit_storage', kwargs={'pk': obj.pk})) def get_context_data(self, **kwargs): context = super(StorageCreate, self).get_context_data(**kwargs) @@ -89,8 +91,9 @@ def create_new_external_recipe(request, import_id): if request.method == "POST": form = ImportRecipeForm(request.POST) if form.is_valid(): - new_recipe = RecipeImport.objects.get(id=import_id) + new_recipe = get_object_or_404(RecipeImport, pk=import_id, space=request.space) recipe = Recipe() + recipe.space = request.space recipe.storage = new_recipe.storage recipe.name = form.cleaned_data['name'] recipe.file_path = form.cleaned_data['file_path'] @@ -101,20 +104,14 @@ def create_new_external_recipe(request, import_id): recipe.keywords.set(form.cleaned_data['keywords']) - RecipeImport.objects.get(id=import_id).delete() + new_recipe.delete() - messages.add_message( - request, messages.SUCCESS, _('Imported new recipe!') - ) + messages.add_message(request, messages.SUCCESS, _('Imported new recipe!')) return redirect('list_recipe_import') else: - messages.add_message( - request, - messages.ERROR, - _('There was an error importing this recipe!') - ) + messages.add_message(request, messages.ERROR, _('There was an error importing this recipe!')) else: - new_recipe = RecipeImport.objects.get(id=import_id) + new_recipe = get_object_or_404(RecipeImport, pk=import_id, space=request.space) form = ImportRecipeForm( initial={ 'file_path': new_recipe.file_path, @@ -136,6 +133,7 @@ class RecipeBookCreate(GroupRequiredMixin, CreateView): def form_valid(self, form): obj = form.save(commit=False) obj.created_by = self.request.user + obj.space = self.request.space obj.save() return HttpResponseRedirect(reverse('view_books')) @@ -154,9 +152,7 @@ class MealPlanCreate(GroupRequiredMixin, CreateView): def get_form(self, form_class=None): form = self.form_class(**self.get_form_kwargs()) - form.fields['meal_type'].queryset = MealType.objects.filter( - created_by=self.request.user - ).all() + form.fields['meal_type'].queryset = MealType.objects.filter(created_by=self.request.user, space=self.request.space).all() return form def get_initial(self): @@ -181,6 +177,7 @@ class MealPlanCreate(GroupRequiredMixin, CreateView): def form_valid(self, form): obj = form.save(commit=False) obj.created_by = self.request.user + obj.space = self.request.space obj.save() return HttpResponseRedirect(reverse('view_plan')) @@ -191,8 +188,8 @@ class MealPlanCreate(GroupRequiredMixin, CreateView): recipe = self.request.GET.get('recipe') if recipe: if re.match(r'^([0-9])+$', recipe): - if Recipe.objects.filter(pk=int(recipe)).exists(): - context['default_recipe'] = Recipe.objects.get(pk=int(recipe)) # noqa: E501 + if Recipe.objects.filter(pk=int(recipe), space=self.request.space).exists(): + context['default_recipe'] = Recipe.objects.get(pk=int(recipe), space=self.request.space) return context @@ -206,6 +203,7 @@ class InviteLinkCreate(GroupRequiredMixin, CreateView): def form_valid(self, form): obj = form.save(commit=False) obj.created_by = self.request.user + obj.space = self.request.space obj.save() return HttpResponseRedirect(reverse('list_invite_link')) diff --git a/cookbook/views/views.py b/cookbook/views/views.py index bb122d70..a20da69c 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -16,6 +16,7 @@ from django.shortcuts import get_object_or_404, render, redirect from django.urls import reverse, reverse_lazy from django.utils import timezone from django.utils.translation import gettext as _ +from django_scopes import scopes_disabled, scope from django_tables2 import RequestConfig from rest_framework.authtoken.models import Token @@ -33,10 +34,12 @@ from recipes.version import BUILD_REF, VERSION_NUMBER def index(request): - if not request.user.is_authenticated: - if User.objects.count() < 1 and 'django.contrib.auth.backends.RemoteUserBackend' not in settings.AUTHENTICATION_BACKENDS: - return HttpResponseRedirect(reverse_lazy('view_setup')) - return HttpResponseRedirect(reverse_lazy('view_search')) + with scopes_disabled(): + if not request.user.is_authenticated: + if User.objects.count() < 1 and 'django.contrib.auth.backends.RemoteUserBackend' not in settings.AUTHENTICATION_BACKENDS: + return HttpResponseRedirect(reverse_lazy('view_setup')) + return HttpResponseRedirect(reverse_lazy('view_search')) + try: page_map = { UserPreference.SEARCH: reverse_lazy('view_search'), @@ -53,7 +56,7 @@ def search(request): if has_group_permission(request.user, ('guest',)): f = RecipeFilter( request.GET, - queryset=Recipe.objects.all().order_by('name') + queryset=Recipe.objects.filter(space=request.user.userpreference.space).all().order_by('name') ) if request.user.userpreference.search_style == UserPreference.LARGE: @@ -63,10 +66,7 @@ def search(request): RequestConfig(request, paginate={'per_page': 25}).configure(table) if request.GET == {} and request.user.userpreference.show_recent: - qs = Recipe.objects \ - .filter(viewlog__created_by=request.user) \ - .order_by('-viewlog__created_at') \ - .all() + qs = Recipe.objects.filter(viewlog__created_by=request.user).filter(space=request.user.userpreference.space).order_by('-viewlog__created_at').all() recent_list = [] for r in qs: @@ -79,11 +79,7 @@ def search(request): else: last_viewed = None - return render( - request, - 'index.html', - {'recipes': table, 'filter': f, 'last_viewed': last_viewed} - ) + return render(request, 'index.html', {'recipes': table, 'filter': f, 'last_viewed': last_viewed}) else: return HttpResponseRedirect(reverse('view_no_group') + '?next=' + request.path) @@ -97,17 +93,14 @@ def no_groups(request): def recipe_view(request, pk, share=None): - recipe = get_object_or_404(Recipe, pk=pk) + with scopes_disabled(): + recipe = get_object_or_404(Recipe, pk=pk) - if not has_group_permission(request.user, ('guest',)) and not share_link_valid(recipe, share): - messages.add_message( - request, - messages.ERROR, - _('You do not have the required permissions to view this page!') - ) + if not (has_group_permission(request.user, ('guest',)) and recipe.space == request.space) and not share_link_valid(recipe, share): + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) return HttpResponseRedirect(reverse('view_no_group') + '?next=' + request.path) - comments = Comment.objects.filter(recipe=recipe) + comments = Comment.objects.filter(recipe__space=request.space, recipe=recipe) if request.method == "POST": if not request.user.is_authenticated: @@ -146,17 +139,9 @@ def recipe_view(request, pk, share=None): bookmark.save() except IntegrityError as e: if 'UNIQUE constraint' in str(e.args): - messages.add_message( - request, - messages.ERROR, - _('This recipe is already linked to the book!') - ) + messages.add_message(request, messages.ERROR, _('This recipe is already linked to the book!')) else: - messages.add_message( - request, - messages.SUCCESS, - _('Bookmark saved!') - ) + messages.add_message(request, messages.SUCCESS, _('Bookmark saved!')) comment_form = CommentForm() @@ -165,20 +150,16 @@ def recipe_view(request, pk, share=None): user_servings = CookLog.objects.filter( recipe=recipe, created_by=request.user, - servings__gt=0 + servings__gt=0, + space=request.space, ).all().aggregate(Avg('servings'))['servings__avg'] if not user_servings: user_servings = 0 if request.user.is_authenticated: - if not ViewLog.objects \ - .filter(recipe=recipe) \ - .filter(created_by=request.user) \ - .filter(created_at__gt=( - timezone.now() - timezone.timedelta(minutes=5))) \ - .exists(): - ViewLog.objects.create(recipe=recipe, created_by=request.user) + if not ViewLog.objects.filter(recipe=recipe, created_by=request.user, created_at__gt=(timezone.now() - timezone.timedelta(minutes=5)), space=request.space).exists(): + ViewLog.objects.create(recipe=recipe, created_by=request.user, space=request.space) return render(request, 'recipe_view.html', {'recipe': recipe, 'comments': comments, 'comment_form': comment_form, 'share': share, 'user_servings': user_servings}) @@ -187,11 +168,9 @@ def recipe_view(request, pk, share=None): def books(request): book_list = [] - books = RecipeBook.objects.filter( - Q(created_by=request.user) | Q(shared=request.user) - ).distinct().all() + recipe_books = RecipeBook.objects.filter(Q(created_by=request.user) | Q(shared=request.user), space=request.space).distinct().all() - for b in books: + for b in recipe_books: book_list.append( { 'book': b, @@ -209,32 +188,24 @@ def meal_plan(request): @group_required('user') def meal_plan_entry(request, pk): - plan = MealPlan.objects.get(pk=pk) + plan = MealPlan.objects.filter(space=request.space).get(pk=pk) if plan.created_by != request.user and plan.shared != request.user: - messages.add_message( - request, - messages.ERROR, - _('You do not have the required permissions to view this page!') - ) + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) return HttpResponseRedirect(reverse_lazy('index')) same_day_plan = MealPlan.objects \ - .filter(date=plan.date) \ + .filter(date=plan.date, space=request.space) \ .exclude(pk=plan.pk) \ .filter(Q(created_by=request.user) | Q(shared=request.user)) \ .order_by('meal_type').all() - return render( - request, - 'meal_plan_entry.html', - {'plan': plan, 'same_day_plan': same_day_plan} - ) + return render(request, 'meal_plan_entry.html', {'plan': plan, 'same_day_plan': same_day_plan}) @group_required('user') def latest_shopping_list(request): - sl = ShoppingList.objects.filter(Q(created_by=request.user) | Q(shared=request.user)).filter(finished=False).order_by('-created_at').first() + sl = ShoppingList.objects.filter(Q(created_by=request.user) | Q(shared=request.user)).filter(finished=False, space=request.space).order_by('-created_at').first() if sl: return HttpResponseRedirect(reverse('view_shopping', kwargs={'pk': sl.pk}) + '?edit=true') @@ -251,7 +222,7 @@ def shopping_list(request, pk=None): r = r.replace('[', '').replace(']', '') if re.match(r'^([0-9])+,([0-9])+[.]*([0-9])*$', r): rid, multiplier = r.split(',') - if recipe := Recipe.objects.filter(pk=int(rid)).first(): + if recipe := Recipe.objects.filter(pk=int(rid), space=request.space).first(): recipes.append({'recipe': recipe.id, 'multiplier': multiplier}) edit = True if 'edit' in request.GET and request.GET['edit'] == 'true' else False @@ -317,23 +288,19 @@ def user_settings(request): if (api_token := Token.objects.filter(user=request.user).first()) is None: api_token = Token.objects.create(user=request.user) - return render( - request, - 'settings.html', - { - 'preference_form': preference_form, - 'user_name_form': user_name_form, - 'password_form': password_form, - 'api_token': api_token - } - ) + return render(request, 'settings.html', { + 'preference_form': preference_form, + 'user_name_form': user_name_form, + 'password_form': password_form, + 'api_token': api_token + }) @group_required('guest') def history(request): view_log = ViewLogTable( ViewLog.objects.filter( - created_by=request.user + created_by=request.user, space=request.space ).order_by('-created_at').all() ) cook_log = CookLogTable( @@ -341,11 +308,7 @@ def history(request): created_by=request.user ).order_by('-created_at').all() ) - return render( - request, - 'history.html', - {'view_log': view_log, 'cook_log': cook_log} - ) + return render(request, 'history.html', {'view_log': view_log, 'cook_log': cook_log}) @group_required('admin') @@ -357,28 +320,22 @@ def system(request): secret_key = False if os.getenv('SECRET_KEY') else True - return render( - request, - 'system.html', - { - 'gunicorn_media': settings.GUNICORN_MEDIA, - 'debug': settings.DEBUG, - 'postgres': postgres, - 'version': VERSION_NUMBER, - 'ref': BUILD_REF, - 'secret_key': secret_key - } - ) + return render(request, 'system.html', { + 'gunicorn_media': settings.GUNICORN_MEDIA, + 'debug': settings.DEBUG, + 'postgres': postgres, + 'version': VERSION_NUMBER, + 'ref': BUILD_REF, + 'secret_key': secret_key + }) def setup(request): if (User.objects.count() > 0 or 'django.contrib.auth.backends.RemoteUserBackend' in settings.AUTHENTICATION_BACKENDS): # noqa: E501 - messages.add_message( - request, - messages.ERROR, - _('The setup page can only be used to create the first user! If you have forgotten your superuser credentials please consult the django documentation on how to reset passwords.') # noqa: E501 - ) + messages.add_message(request, messages.ERROR, + _('The setup page can only be used to create the first user! If you have forgotten your superuser credentials please consult the django documentation on how to reset passwords.') # noqa: E501 + ) return HttpResponseRedirect(reverse('account_login')) if request.method == 'POST': @@ -415,14 +372,10 @@ def signup(request, token): try: token = UUID(token, version=4) except ValueError: - messages.add_message( - request, messages.ERROR, _('Malformed Invite Link supplied!') - ) + messages.add_message(request, messages.ERROR, _('Malformed Invite Link supplied!')) return HttpResponseRedirect(reverse('index')) - if link := InviteLink.objects.filter( - valid_until__gte=datetime.today(), used_by=None, uuid=token) \ - .first(): + if link := InviteLink.objects.filter(valid_until__gte=datetime.today(), used_by=None, uuid=token).first(): if request.method == 'POST': updated_request = request.POST.copy() if link.username != '': diff --git a/recipes/settings.py b/recipes/settings.py index 3105c67f..f942e451 100644 --- a/recipes/settings.py +++ b/recipes/settings.py @@ -101,6 +101,7 @@ MIDDLEWARE = [ 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'cookbook.helper.scope_middleware.ScopeMiddleware', ] # Auth related settings From ad163509b4ce6eacaf49f267cbcf54ab8924f45c Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Fri, 19 Feb 2021 18:09:42 +0100 Subject: [PATCH 11/96] updated edit and added space find methods --- cookbook/helper/permission_helper.py | 20 ++++-- cookbook/helper/scope_middleware.py | 3 +- cookbook/models.py | 103 ++++++++++++++++----------- cookbook/views/edit.py | 52 +++++--------- cookbook/views/import_export.py | 2 +- 5 files changed, 96 insertions(+), 84 deletions(-) diff --git a/cookbook/helper/permission_helper.py b/cookbook/helper/permission_helper.py index f6db4d81..21e4c196 100644 --- a/cookbook/helper/permission_helper.py +++ b/cookbook/helper/permission_helper.py @@ -1,6 +1,9 @@ """ Source: https://djangosnippets.org/snippets/1703/ """ +from django.views.generic.detail import SingleObjectTemplateResponseMixin +from django.views.generic.edit import ModelFormMixin + from cookbook.models import ShareLink from django.contrib import messages from django.contrib.auth.decorators import user_passes_test @@ -131,11 +134,11 @@ class GroupRequiredMixin(object): def dispatch(self, request, *args, **kwargs): if not has_group_permission(request.user, self.groups_required): - messages.add_message( - request, - messages.ERROR, - _('You do not have the required permissions to view this page!') # noqa: E501 - ) + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) + return HttpResponseRedirect(reverse_lazy('index')) + + if self.get_object().get_space() != request.space: + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) return HttpResponseRedirect(reverse_lazy('index')) return super(GroupRequiredMixin, self).dispatch(request, *args, **kwargs) @@ -162,8 +165,11 @@ class OwnerRequiredMixin(object): ) return HttpResponseRedirect(reverse('index')) - return super(OwnerRequiredMixin, self) \ - .dispatch(request, *args, **kwargs) + if self.get_object().get_space() != request.space: + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) + return HttpResponseRedirect(reverse_lazy('index')) + + return super(OwnerRequiredMixin, self).dispatch(request, *args, **kwargs) # Django Rest Framework Permission classes diff --git a/cookbook/helper/scope_middleware.py b/cookbook/helper/scope_middleware.py index 595a5f91..0bf415b8 100644 --- a/cookbook/helper/scope_middleware.py +++ b/cookbook/helper/scope_middleware.py @@ -1,4 +1,4 @@ -from django_scopes import scope +from django_scopes import scope, scopes_disabled class ScopeMiddleware: @@ -9,6 +9,7 @@ class ScopeMiddleware: if request.user.is_authenticated: request.space = request.user.userpreference.space + #with scopes_disabled(): with scope(space=request.space): return self.get_response(request) else: diff --git a/cookbook/models.py b/cookbook/models.py index fd6ca6ce..dd3b1098 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -9,7 +9,6 @@ from django.core.validators import MinLengthValidator from django.db import models from django.utils import timezone from django.utils.translation import gettext as _ -from django_random_queryset import RandomManager from django_scopes import ScopedManager from recipes.settings import (COMMENT_PREF_DEFAULT, FRACTION_PREF_DEFAULT, @@ -30,12 +29,26 @@ def get_model_name(model): return ('_'.join(re.findall('[A-Z][^A-Z]*', model.__name__))).lower() +class PermissionModelMixin: + def get_owner(self): + if getattr(self, 'created_by', None): + return self.created_by + if getattr(self, 'user', None): + return self.user + return None + + def get_space(self): + if getattr(self, 'space', None): + return self.space + raise NotImplementedError('get space for method not implemented and standard fields not available') + + class Space(models.Model): name = models.CharField(max_length=128, default='Default') message = models.CharField(max_length=512, default='', blank=True) -class UserPreference(models.Model): +class UserPreference(models.Model, PermissionModelMixin): # Themes BOOTSTRAP = 'BOOTSTRAP' DARKLY = 'DARKLY' @@ -115,7 +128,7 @@ class UserPreference(models.Model): return str(self.user) -class Storage(models.Model): +class Storage(models.Model, PermissionModelMixin): DROPBOX = 'DB' NEXTCLOUD = 'NEXTCLOUD' LOCAL = 'LOCAL' @@ -139,7 +152,7 @@ class Storage(models.Model): return self.name -class Sync(models.Model): +class Sync(models.Model, PermissionModelMixin): storage = models.ForeignKey(Storage, on_delete=models.PROTECT) path = models.CharField(max_length=512, default="") active = models.BooleanField(default=True) @@ -154,7 +167,7 @@ class Sync(models.Model): return self.path -class SupermarketCategory(models.Model): +class SupermarketCategory(models.Model, PermissionModelMixin): name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) @@ -165,7 +178,7 @@ class SupermarketCategory(models.Model): return self.name -class Supermarket(models.Model): +class Supermarket(models.Model, PermissionModelMixin): name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) categories = models.ManyToManyField(SupermarketCategory, through='SupermarketCategoryRelation') @@ -177,18 +190,21 @@ class Supermarket(models.Model): return self.name -class SupermarketCategoryRelation(models.Model): +class SupermarketCategoryRelation(models.Model, PermissionModelMixin): supermarket = models.ForeignKey(Supermarket, on_delete=models.CASCADE, related_name='category_to_supermarket') category = models.ForeignKey(SupermarketCategory, on_delete=models.CASCADE, related_name='category_to_supermarket') order = models.IntegerField(default=0) objects = ScopedManager(space='supermarket__space') + def get_space(self): + return self.supermarket.space + class Meta: ordering = ('order',) -class SyncLog(models.Model): +class SyncLog(models.Model, PermissionModelMixin): sync = models.ForeignKey(Sync, on_delete=models.CASCADE) status = models.CharField(max_length=32) msg = models.TextField(default="") @@ -201,7 +217,7 @@ class SyncLog(models.Model): return f"{self.created_at}:{self.sync} - {self.status}" -class Keyword(models.Model): +class Keyword(models.Model, PermissionModelMixin): name = models.CharField(max_length=64, unique=True) icon = models.CharField(max_length=16, blank=True, null=True) description = models.TextField(default="", blank=True) @@ -218,7 +234,7 @@ class Keyword(models.Model): return f"{self.name}" -class Unit(models.Model): +class Unit(models.Model, PermissionModelMixin): name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) @@ -229,7 +245,7 @@ class Unit(models.Model): return self.name -class Food(models.Model): +class Food(models.Model, PermissionModelMixin): name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) recipe = models.ForeignKey('Recipe', null=True, blank=True, on_delete=models.SET_NULL) supermarket_category = models.ForeignKey(SupermarketCategory, null=True, blank=True, on_delete=models.SET_NULL) @@ -243,13 +259,9 @@ class Food(models.Model): return self.name -class Ingredient(models.Model): - food = models.ForeignKey( - Food, on_delete=models.PROTECT, null=True, blank=True - ) - unit = models.ForeignKey( - Unit, on_delete=models.PROTECT, null=True, blank=True - ) +class Ingredient(models.Model, PermissionModelMixin): + food = models.ForeignKey(Food, on_delete=models.PROTECT, null=True, blank=True) + unit = models.ForeignKey(Unit, on_delete=models.PROTECT, null=True, blank=True) amount = models.DecimalField(default=0, decimal_places=16, max_digits=32) note = models.CharField(max_length=256, null=True, blank=True) is_header = models.BooleanField(default=False) @@ -258,6 +270,9 @@ class Ingredient(models.Model): objects = ScopedManager(space='step__recipe__space') + def get_space(self): + return self.step_set.first().recipe_set.first().space + def __str__(self): return str(self.amount) + ' ' + str(self.unit) + ' ' + str(self.food) @@ -265,7 +280,7 @@ class Ingredient(models.Model): ordering = ['order', 'pk'] -class Step(models.Model): +class Step(models.Model, PermissionModelMixin): TEXT = 'TEXT' TIME = 'TIME' @@ -283,6 +298,9 @@ class Step(models.Model): objects = ScopedManager(space='recipe__space') + def get_space(self): + return self.recipe_set.first().space + def get_instruction_render(self): from cookbook.helper.template_helper import render_instructions return render_instructions(self) @@ -291,7 +309,7 @@ class Step(models.Model): ordering = ['order', 'pk'] -class NutritionInformation(models.Model): +class NutritionInformation(models.Model, PermissionModelMixin): fats = models.DecimalField(default=0, decimal_places=16, max_digits=32) carbohydrates = models.DecimalField( default=0, decimal_places=16, max_digits=32 @@ -304,11 +322,14 @@ class NutritionInformation(models.Model): objects = ScopedManager(space='recipe__space') + def get_space(self): + return self.recipe_set.first().space + def __str__(self): return 'Nutrition' -class Recipe(models.Model): +class Recipe(models.Model, PermissionModelMixin): name = models.CharField(max_length=128) description = models.CharField(max_length=512, blank=True, null=True) servings = models.IntegerField(default=1) @@ -340,7 +361,7 @@ class Recipe(models.Model): return self.name -class Comment(models.Model): +class Comment(models.Model, PermissionModelMixin): recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE) text = models.TextField() created_by = models.ForeignKey(User, on_delete=models.CASCADE) @@ -349,11 +370,14 @@ class Comment(models.Model): objects = ScopedManager(space='recipe__space') + def get_space(self): + return self.recipe.space + def __str__(self): return self.text -class RecipeImport(models.Model): +class RecipeImport(models.Model, PermissionModelMixin): name = models.CharField(max_length=128) storage = models.ForeignKey(Storage, on_delete=models.PROTECT) file_uid = models.CharField(max_length=256, default="") @@ -367,13 +391,11 @@ class RecipeImport(models.Model): return self.name -class RecipeBook(models.Model): +class RecipeBook(models.Model, PermissionModelMixin): name = models.CharField(max_length=128) description = models.TextField(blank=True) icon = models.CharField(max_length=16, blank=True, null=True) - shared = models.ManyToManyField( - User, blank=True, related_name='shared_with' - ) + shared = models.ManyToManyField(User, blank=True, related_name='shared_with') created_by = models.ForeignKey(User, on_delete=models.CASCADE) space = models.ForeignKey(Space, on_delete=models.CASCADE) @@ -383,12 +405,15 @@ class RecipeBook(models.Model): return self.name -class RecipeBookEntry(models.Model): +class RecipeBookEntry(models.Model, PermissionModelMixin): recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE) book = models.ForeignKey(RecipeBook, on_delete=models.CASCADE) objects = ScopedManager(space='book__space') + def get_space(self): + return self.book.space + def __str__(self): return self.recipe.name @@ -402,7 +427,7 @@ class RecipeBookEntry(models.Model): unique_together = (('recipe', 'book'),) -class MealType(models.Model): +class MealType(models.Model, PermissionModelMixin): name = models.CharField(max_length=128) order = models.IntegerField(default=0) created_by = models.ForeignKey(User, on_delete=models.CASCADE) @@ -414,7 +439,7 @@ class MealType(models.Model): return self.name -class MealPlan(models.Model): +class MealPlan(models.Model, PermissionModelMixin): recipe = models.ForeignKey( Recipe, on_delete=models.CASCADE, blank=True, null=True ) @@ -443,10 +468,8 @@ class MealPlan(models.Model): return f'{self.get_label()} - {self.date} - {self.meal_type.name}' -class ShoppingListRecipe(models.Model): - recipe = models.ForeignKey( - Recipe, on_delete=models.CASCADE, null=True, blank=True - ) +class ShoppingListRecipe(models.Model, PermissionModelMixin): + recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, null=True, blank=True) servings = models.DecimalField(default=1, max_digits=8, decimal_places=4) space = models.ForeignKey(Space, on_delete=models.CASCADE) @@ -462,7 +485,7 @@ class ShoppingListRecipe(models.Model): return None -class ShoppingListEntry(models.Model): +class ShoppingListEntry(models.Model, PermissionModelMixin): list_recipe = models.ForeignKey(ShoppingListRecipe, on_delete=models.CASCADE, null=True, blank=True) food = models.ForeignKey(Food, on_delete=models.CASCADE) unit = models.ForeignKey(Unit, on_delete=models.CASCADE, null=True, blank=True) @@ -483,7 +506,7 @@ class ShoppingListEntry(models.Model): return None -class ShoppingList(models.Model): +class ShoppingList(models.Model, PermissionModelMixin): uuid = models.UUIDField(default=uuid.uuid4) note = models.TextField(blank=True, null=True) recipes = models.ManyToManyField(ShoppingListRecipe, blank=True) @@ -501,7 +524,7 @@ class ShoppingList(models.Model): return f'Shopping list {self.id}' -class ShareLink(models.Model): +class ShareLink(models.Model, PermissionModelMixin): recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE) uuid = models.UUIDField(default=uuid.uuid4) created_by = models.ForeignKey(User, on_delete=models.CASCADE) @@ -518,7 +541,7 @@ def default_valid_until(): return date.today() + timedelta(days=14) -class InviteLink(models.Model): +class InviteLink(models.Model, PermissionModelMixin): uuid = models.UUIDField(default=uuid.uuid4) username = models.CharField(blank=True, max_length=64) group = models.ForeignKey(Group, on_delete=models.CASCADE) @@ -536,7 +559,7 @@ class InviteLink(models.Model): return f'{self.uuid}' -class CookLog(models.Model): +class CookLog(models.Model, PermissionModelMixin): recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE) created_by = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(default=timezone.now) @@ -550,7 +573,7 @@ class CookLog(models.Model): return self.recipe.name -class ViewLog(models.Model): +class ViewLog(models.Model, PermissionModelMixin): recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE) created_by = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) diff --git a/cookbook/views/edit.py b/cookbook/views/edit.py index 4259fc97..e1913a9a 100644 --- a/cookbook/views/edit.py +++ b/cookbook/views/edit.py @@ -3,9 +3,10 @@ import os from django.contrib import messages from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render -from django.urls import reverse +from django.urls import reverse, reverse_lazy from django.utils.translation import gettext as _ from django.views.generic import UpdateView +from django_scopes import scopes_disabled from cookbook.forms import (CommentForm, ExternalRecipeForm, FoodForm, FoodMergeForm, KeywordForm, MealPlanForm, @@ -24,7 +25,7 @@ from cookbook.provider.nextcloud import Nextcloud @group_required('guest') def switch_recipe(request, pk): - recipe = get_object_or_404(Recipe, pk=pk) + recipe = get_object_or_404(Recipe, pk=pk, space=request.space) if recipe.internal: return HttpResponseRedirect(reverse('edit_internal_recipe', args=[pk])) else: @@ -33,7 +34,7 @@ def switch_recipe(request, pk): @group_required('user') def convert_recipe(request, pk): - recipe = get_object_or_404(Recipe, pk=pk) + recipe = get_object_or_404(Recipe, pk=pk, space=request.space) if not recipe.internal: recipe.internal = True recipe.save() @@ -43,7 +44,7 @@ def convert_recipe(request, pk): @group_required('user') def internal_recipe_update(request, pk): - recipe_instance = get_object_or_404(Recipe, pk=pk) + recipe_instance = get_object_or_404(Recipe, pk=pk, space=request.space) return render( request, 'forms/edit_internal_recipe.html', {'recipe': recipe_instance} @@ -62,7 +63,7 @@ class SyncUpdate(GroupRequiredMixin, UpdateView): return reverse('edit_sync', kwargs={'pk': self.object.pk}) def get_context_data(self, **kwargs): - context = super(SyncUpdate, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) context['title'] = _("Sync") return context @@ -79,7 +80,7 @@ class KeywordUpdate(GroupRequiredMixin, UpdateView): return reverse('edit_keyword', kwargs={'pk': self.object.pk}) def get_context_data(self, **kwargs): - context = super(KeywordUpdate, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) context['title'] = _("Keyword") return context @@ -103,12 +104,10 @@ class FoodUpdate(GroupRequiredMixin, UpdateView): @group_required('admin') def edit_storage(request, pk): - instance = get_object_or_404(Storage, pk=pk) + instance = get_object_or_404(Storage, pk=pk, space=request.space) if not (instance.created_by == request.user or request.user.is_superuser): - messages.add_message( - request, messages.ERROR, _('You cannot edit this storage!') - ) + messages.add_message(request, messages.ERROR, _('You cannot edit this storage!')) return HttpResponseRedirect(reverse('list_storage')) if request.method == "POST": @@ -225,7 +224,7 @@ class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView): def form_valid(self, form): self.object = form.save(commit=False) - old_recipe = Recipe.objects.get(pk=self.object.pk) + old_recipe = Recipe.objects.get(pk=self.object.pk, space=self.request.space) if not old_recipe.name == self.object.name: if self.object.storage.method == Storage.DROPBOX: # TODO central location to handle storage type switches @@ -277,45 +276,32 @@ def edit_ingredients(request): new_unit = units_form.cleaned_data['new_unit'] old_unit = units_form.cleaned_data['old_unit'] if new_unit != old_unit: - recipe_ingredients = Ingredient.objects \ - .filter(unit=old_unit).all() + recipe_ingredients = Ingredient.objects.filter(unit=old_unit, space=request.space).all() for i in recipe_ingredients: i.unit = new_unit i.save() old_unit.delete() success = True - messages.add_message( - request, messages.SUCCESS, _('Units merged!') - ) + messages.add_message(request, messages.SUCCESS, _('Units merged!')) else: - messages.add_message( - request, - messages.ERROR, - _('Cannot merge with the same object!') - ) + messages.add_message(request, messages.ERROR, _('Cannot merge with the same object!')) food_form = FoodMergeForm(request.POST, prefix=FoodMergeForm.prefix) if food_form.is_valid(): new_food = food_form.cleaned_data['new_food'] old_food = food_form.cleaned_data['old_food'] if new_food != old_food: - ingredients = Ingredient.objects.filter(food=old_food).all() + ingredients = Ingredient.objects.filter(food=old_food, space=request.space).all() for i in ingredients: i.food = new_food i.save() old_food.delete() success = True - messages.add_message( - request, messages.SUCCESS, _('Foods merged!') - ) + messages.add_message(request, messages.SUCCESS, _('Foods merged!')) else: - messages.add_message( - request, - messages.ERROR, - _('Cannot merge with the same object!') - ) + messages.add_message(request, messages.ERROR, _('Cannot merge with the same object!')) if success: units_form = UnitMergeForm() @@ -324,8 +310,4 @@ def edit_ingredients(request): units_form = UnitMergeForm() food_form = FoodMergeForm() - return render( - request, - 'forms/ingredients.html', - {'units_form': units_form, 'food_form': food_form} - ) + return render(request, 'forms/ingredients.html', {'units_form': units_form, 'food_form': food_form}) diff --git a/cookbook/views/import_export.py b/cookbook/views/import_export.py index a77113d5..d7ea9de0 100644 --- a/cookbook/views/import_export.py +++ b/cookbook/views/import_export.py @@ -62,7 +62,7 @@ def export_recipe(request): recipe = request.GET.get('r') if recipe: if re.match(r'^([0-9])+$', recipe): - if recipe := Recipe.objects.filter(pk=int(recipe)).first(): + if recipe := Recipe.objects.filter(pk=int(recipe), space=request.space).first(): form = ExportForm(initial={'recipes': recipe}, user=request.user) return render(request, 'export.html', {'form': form}) From a44f72a03027ba0835eb5a356db3170cbf847e20 Mon Sep 17 00:00:00 2001 From: Vegetto Date: Sat, 20 Feb 2021 16:42:48 +0100 Subject: [PATCH 12/96] Add DB_OPTIONS to enable DBs with SSL --- recipes/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/recipes/settings.py b/recipes/settings.py index 3105c67f..1c56f5df 100644 --- a/recipes/settings.py +++ b/recipes/settings.py @@ -175,6 +175,7 @@ WSGI_APPLICATION = 'recipes.wsgi.application' DATABASES = { 'default': { 'ENGINE': os.getenv('DB_ENGINE') if os.getenv('DB_ENGINE') else 'django.db.backends.sqlite3', + 'OPTIONS': os.getenv('DB_OPTIONS') if os.getenv('DB_OPTIONS') else [], 'HOST': os.getenv('POSTGRES_HOST'), 'PORT': os.getenv('POSTGRES_PORT'), 'USER': os.getenv('POSTGRES_USER'), From 5aa918f478379bb5c622149de3ed6fa46387e980 Mon Sep 17 00:00:00 2001 From: Vegetto Date: Sat, 20 Feb 2021 16:53:02 +0100 Subject: [PATCH 13/96] Document DB_OPTIONS env --- .env.template | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.template b/.env.template index ecc63919..1146dd9f 100644 --- a/.env.template +++ b/.env.template @@ -13,6 +13,7 @@ TIMEZONE=Europe/Berlin # add only a database password if you want to run with the default postgres, otherwise change settings accordingly DB_ENGINE=django.db.backends.postgresql +# DB_OPTIONS= {} POSTGRES_HOST=db_recipes POSTGRES_PORT=5432 POSTGRES_USER=djangouser From 804adde964886160707c7b95cfe7dce940d777e3 Mon Sep 17 00:00:00 2001 From: Vegetto Date: Sat, 20 Feb 2021 16:54:42 +0100 Subject: [PATCH 14/96] Parse DB_OPTIONS dict --- recipes/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recipes/settings.py b/recipes/settings.py index 1c56f5df..8f04a4d5 100644 --- a/recipes/settings.py +++ b/recipes/settings.py @@ -175,7 +175,7 @@ WSGI_APPLICATION = 'recipes.wsgi.application' DATABASES = { 'default': { 'ENGINE': os.getenv('DB_ENGINE') if os.getenv('DB_ENGINE') else 'django.db.backends.sqlite3', - 'OPTIONS': os.getenv('DB_OPTIONS') if os.getenv('DB_OPTIONS') else [], + 'OPTIONS': ast.literal_eval(os.getenv('DB_OPTIONS')) if os.getenv('DB_OPTIONS') else {}, 'HOST': os.getenv('POSTGRES_HOST'), 'PORT': os.getenv('POSTGRES_PORT'), 'USER': os.getenv('POSTGRES_USER'), From 96c963795e373d8bdfe9d86a182d963a54a91007 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sat, 20 Feb 2021 18:47:14 +0100 Subject: [PATCH 15/96] more spaces work --- cookbook/helper/permission_helper.py | 40 +++++----------------- cookbook/provider/dropbox.py | 15 ++++---- cookbook/provider/local.py | 9 ++--- cookbook/provider/nextcloud.py | 18 ++++------ cookbook/views/data.py | 51 ++++++++++++---------------- cookbook/views/delete.py | 17 ++-------- 6 files changed, 50 insertions(+), 100 deletions(-) diff --git a/cookbook/helper/permission_helper.py b/cookbook/helper/permission_helper.py index 21e4c196..fa9e1200 100644 --- a/cookbook/helper/permission_helper.py +++ b/cookbook/helper/permission_helper.py @@ -43,8 +43,7 @@ def has_group_permission(user, groups): return False groups_allowed = get_allowed_groups(groups) if user.is_authenticated: - if (user.is_superuser - | bool(user.groups.filter(name__in=groups_allowed))): + if bool(user.groups.filter(name__in=groups_allowed)): return True return False @@ -59,19 +58,12 @@ def is_object_owner(user, obj): :param obj any object that should be tested :return: true if user is owner of object, false otherwise """ - # TODO this could be improved/cleaned up by adding - # get_owner methods to all models that allow owner checks if not user.is_authenticated: return False - if user.is_superuser: - return True - if owner := getattr(obj, 'created_by', None): - return owner == user - if owner := getattr(obj, 'user', None): - return owner == user - if getattr(obj, 'get_owner', None): + try: return obj.get_owner() == user - return False + except: + return False def is_object_shared(user, obj): @@ -87,8 +79,6 @@ def is_object_shared(user, obj): # share checks for relevant objects if not user.is_authenticated: return False - if user.is_superuser: - return True return user in obj.shared.all() @@ -100,11 +90,7 @@ def share_link_valid(recipe, share): :return: true if a share link with the given recipe and uuid exists """ try: - return ( - True - if ShareLink.objects.filter(recipe=recipe, uuid=share).exists() - else False - ) + return True if ShareLink.objects.filter(recipe=recipe, uuid=share).exists() else False except ValidationError: return False @@ -148,21 +134,11 @@ class OwnerRequiredMixin(object): def dispatch(self, request, *args, **kwargs): if not request.user.is_authenticated: - messages.add_message( - request, - messages.ERROR, - _('You are not logged in and therefore cannot view this page!') - ) - return HttpResponseRedirect( - reverse_lazy('account_login') + '?next=' + request.path - ) + messages.add_message(request, messages.ERROR, _('You are not logged in and therefore cannot view this page!')) + return HttpResponseRedirect(reverse_lazy('account_login') + '?next=' + request.path) else: if not is_object_owner(request.user, self.get_object()): - messages.add_message( - request, - messages.ERROR, - _('You cannot interact with this object as it is not owned by you!') # noqa: E501 - ) + messages.add_message(request, messages.ERROR, _('You cannot interact with this object as it is not owned by you!')) return HttpResponseRedirect(reverse('index')) if self.get_object().get_space() != request.space: diff --git a/cookbook/provider/dropbox.py b/cookbook/provider/dropbox.py index 2c81c905..af3d410e 100644 --- a/cookbook/provider/dropbox.py +++ b/cookbook/provider/dropbox.py @@ -27,7 +27,7 @@ class Dropbox(Provider): try: recipes = r.json() except ValueError: - log_entry = SyncLog(status='ERROR', msg=str(r), sync=monitor) + log_entry = SyncLog(status='ERROR', msg=str(r), sync=monitor, space=monitor.space) log_entry.save() return r @@ -35,14 +35,14 @@ class Dropbox(Provider): # TODO check if has_more is set and import that as well for recipe in recipes['entries']: path = recipe['path_lower'] - if not Recipe.objects.filter(file_path__iexact=path).exists() \ - and not RecipeImport.objects.filter(file_path=path).exists(): # noqa: E501 + if not Recipe.objects.filter(file_path__iexact=path, space=monitor.space).exists() and not RecipeImport.objects.filter(file_path=path, space=monitor.space).exists(): name = os.path.splitext(recipe['name'])[0] new_recipe = RecipeImport( name=name, file_path=path, storage=monitor.storage, - file_uid=recipe['id'] + file_uid=recipe['id'], + space=monitor.space, ) new_recipe.save() import_count += 1 @@ -50,7 +50,8 @@ class Dropbox(Provider): log_entry = SyncLog( status='SUCCESS', msg='Imported ' + str(import_count) + ' recipes', - sync=monitor + sync=monitor, + space=monitor.space, ) log_entry.save() @@ -104,9 +105,7 @@ class Dropbox(Provider): recipe.link = Dropbox.get_share_link(recipe) recipe.save() - response = requests.get( - recipe.link.replace('www.dropbox.', 'dl.dropboxusercontent.') - ) + response = requests.get(recipe.link.replace('www.dropbox.', 'dl.dropboxusercontent.')) return io.BytesIO(response.content) diff --git a/cookbook/provider/local.py b/cookbook/provider/local.py index 1ec79157..1298e3e4 100644 --- a/cookbook/provider/local.py +++ b/cookbook/provider/local.py @@ -18,13 +18,13 @@ class Local(Provider): import_count = 0 for file in files: path = monitor.path + '/' + file - if not Recipe.objects.filter(file_path__iexact=path).exists() \ - and not RecipeImport.objects.filter(file_path=path).exists(): # noqa: E501 + if not Recipe.objects.filter(file_path__iexact=path, space=monitor.space).exists() and not RecipeImport.objects.filter(file_path=path, space=monitor.space).exists(): name = os.path.splitext(file)[0] new_recipe = RecipeImport( name=name, file_path=path, - storage=monitor.storage + storage=monitor.storage, + space=monitor.space, ) new_recipe.save() import_count += 1 @@ -32,7 +32,8 @@ class Local(Provider): log_entry = SyncLog( status='SUCCESS', msg='Imported ' + str(import_count) + ' recipes', - sync=monitor + sync=monitor, + space=monitor.space, ) log_entry.save() diff --git a/cookbook/provider/nextcloud.py b/cookbook/provider/nextcloud.py index 81d1f16a..f11109ed 100644 --- a/cookbook/provider/nextcloud.py +++ b/cookbook/provider/nextcloud.py @@ -34,13 +34,13 @@ class Nextcloud(Provider): import_count = 0 for file in files: path = monitor.path + '/' + file - if not Recipe.objects.filter(file_path__iexact=path).exists() \ - and not RecipeImport.objects.filter(file_path=path).exists(): # noqa: E501 + if not Recipe.objects.filter(file_path__iexact=path, space=monitor.space).exists() and not RecipeImport.objects.filter(file_path=path, space=monitor.space).exists(): name = os.path.splitext(file)[0] new_recipe = RecipeImport( name=name, file_path=path, - storage=monitor.storage + storage=monitor.storage, + space=monitor.space, ) new_recipe.save() import_count += 1 @@ -48,7 +48,8 @@ class Nextcloud(Provider): log_entry = SyncLog( status='SUCCESS', msg='Imported ' + str(import_count) + ' recipes', - sync=monitor + sync=monitor, + space=monitor.space ) log_entry.save() @@ -68,14 +69,7 @@ class Nextcloud(Provider): data = {'path': recipe.file_path, 'shareType': 3} - r = requests.post( - url, - headers=headers, - auth=HTTPBasicAuth( - recipe.storage.username, recipe.storage.password - ), - data=data - ) + r = requests.post(url, headers=headers, auth=HTTPBasicAuth(recipe.storage.username, recipe.storage.password), data=data) response_json = r.json() diff --git a/cookbook/views/data.py b/cookbook/views/data.py index 5425e7dc..77081e5f 100644 --- a/cookbook/views/data.py +++ b/cookbook/views/data.py @@ -27,10 +27,7 @@ from cookbook.tables import SyncTable def sync(request): if request.method == "POST": if not has_group_permission(request.user, ['admin']): - messages.add_message( - request, messages.ERROR, - _('You do not have the required permissions to view this page!') # noqa: E501 - ) + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) return HttpResponseRedirect(reverse('data_sync')) form = SyncForm(request.POST) if form.is_valid(): @@ -38,21 +35,16 @@ def sync(request): new_path.path = form.cleaned_data['path'] new_path.storage = form.cleaned_data['storage'] new_path.last_checked = datetime.now() + new_path.space = request.space new_path.save() return redirect('data_sync') else: form = SyncForm() - monitored_paths = SyncTable(Sync.objects.all()) - RequestConfig( - request, paginate={'per_page': 25} - ).configure(monitored_paths) + monitored_paths = SyncTable(Sync.objects.fitler(space=request.space).all()) + RequestConfig(request, paginate={'per_page': 25}).configure(monitored_paths) - return render( - request, - 'batch/monitor.html', - {'form': form, 'monitored_paths': monitored_paths} - ) + return render(request, 'batch/monitor.html', {'form': form, 'monitored_paths': monitored_paths}) @group_required('user') @@ -62,14 +54,15 @@ def sync_wait(request): @group_required('user') def batch_import(request): - imports = RecipeImport.objects.all() + imports = RecipeImport.objects.filter(space=request.space).all() for new_recipe in imports: recipe = Recipe( name=new_recipe.name, file_path=new_recipe.file_path, storage=new_recipe.storage, file_uid=new_recipe.file_uid, - created_by=request.user + created_by=request.user, + space=request.space ) recipe.save() new_recipe.delete() @@ -85,7 +78,7 @@ def batch_edit(request): word = form.cleaned_data['search'] keywords = form.cleaned_data['keywords'] - recipes = Recipe.objects.filter(name__icontains=word) + recipes = Recipe.objects.filter(name__icontains=word, space=request.space) count = 0 for recipe in recipes: edit = False @@ -125,6 +118,7 @@ def import_url(request): servings=data['servings'], internal=True, created_by=request.user, + space=request.space, ) step = Step.objects.create( @@ -134,11 +128,10 @@ def import_url(request): recipe.steps.add(step) for kw in data['keywords']: - if kw['id'] != "null" \ - and (k := Keyword.objects.filter(id=kw['id']).first()): + if kw['id'] != "null" and (k := Keyword.objects.filter(id=kw['id'], space=request.space).first()): recipe.keywords.add(k) elif data['all_keywords']: - k = Keyword.objects.create(name=kw['text']) + k = Keyword.objects.create(name=kw['text'], space=request.space) recipe.keywords.add(k) for ing in data['recipeIngredient']: @@ -146,12 +139,12 @@ def import_url(request): if ing['ingredient']['text'] != '': ingredient.food, f_created = Food.objects.get_or_create( - name=ing['ingredient']['text'] + name=ing['ingredient']['text'], space=request.space ) if ing['unit'] and ing['unit']['text'] != '': ingredient.unit, u_created = Unit.objects.get_or_create( - name=ing['unit']['text'] + name=ing['unit']['text'], space=request.space ) # TODO properly handle no_amount recipes @@ -202,16 +195,16 @@ class Object(object): @group_required('user') def statistics(request): counts = Object() - counts.recipes = Recipe.objects.count() - counts.keywords = Keyword.objects.count() - counts.recipe_import = RecipeImport.objects.count() - counts.units = Unit.objects.count() - counts.ingredients = Food.objects.count() - counts.comments = Comment.objects.count() + counts.recipes = Recipe.objects.filter(space=request.space).count() + counts.keywords = Keyword.objects.filter(space=request.space).count() + counts.recipe_import = RecipeImport.objects.filter(space=request.space).count() + counts.units = Unit.objects.filter(space=request.space).count() + counts.ingredients = Food.objects.filter(space=request.space).count() + counts.comments = Comment.objects.filter(recipe__space=request.space).count() - counts.recipes_internal = Recipe.objects.filter(internal=True).count() + counts.recipes_internal = Recipe.objects.filter(internal=True, space=request.space).count() counts.recipes_external = counts.recipes - counts.recipes_internal - counts.recipes_no_keyword = Recipe.objects.filter(keywords=None).count() + counts.recipes_no_keyword = Recipe.objects.filter(keywords=None, space=request.space).count() return render(request, 'stats.html', {'counts': counts}) diff --git a/cookbook/views/delete.py b/cookbook/views/delete.py index 689ad2f1..cac4250b 100644 --- a/cookbook/views/delete.py +++ b/cookbook/views/delete.py @@ -31,7 +31,7 @@ class RecipeDelete(GroupRequiredMixin, DeleteView): @group_required('user') def delete_recipe_source(request, pk): - recipe = get_object_or_404(Recipe, pk=pk) + recipe = get_object_or_404(Recipe, pk=pk, space=request.space) if recipe.storage.method == Storage.DROPBOX: # TODO central location to handle storage type switches @@ -130,25 +130,12 @@ class RecipeBookDelete(OwnerRequiredMixin, DeleteView): return context -class RecipeBookEntryDelete(GroupRequiredMixin, DeleteView): +class RecipeBookEntryDelete(OwnerRequiredMixin, DeleteView): groups_required = ['user'] template_name = "generic/delete_template.html" model = RecipeBookEntry success_url = reverse_lazy('view_books') - def dispatch(self, request, *args, **kwargs): - obj = self.get_object() - if not (obj.book.created_by == request.user - or request.user.is_superuser): - messages.add_message( - request, - messages.ERROR, - _('You cannot interact with this object as it is not owned by you!') # noqa: E501 - ) - return HttpResponseRedirect(reverse('index')) - return super(RecipeBookEntryDelete, self) \ - .dispatch(request, *args, **kwargs) - def get_context_data(self, **kwargs): context = super(RecipeBookEntryDelete, self).get_context_data(**kwargs) context['title'] = _("Bookmarks") From e2b1115b3b3c27d02c773d4084205304be3224f4 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sat, 20 Feb 2021 18:50:28 +0100 Subject: [PATCH 16/96] fixed servings blank --- cookbook/helper/recipe_url_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/helper/recipe_url_import.py b/cookbook/helper/recipe_url_import.py index 0ff4f1c9..f6b3e478 100644 --- a/cookbook/helper/recipe_url_import.py +++ b/cookbook/helper/recipe_url_import.py @@ -218,13 +218,13 @@ def find_recipe_json(ld_json, url): else: ld_json['prepTime'] = 0 + ld_json['servings'] = 1 try: if 'recipeYield' in ld_json: if type(ld_json['recipeYield']) == str: ld_json['servings'] = int(re.findall(r'\b\d+\b', ld_json['recipeYield'])[0]) except Exception as e: print(e) - ld_json['servings'] = 1 for key in list(ld_json): if key not in [ From d7675d4b808aee6e93520d7581a7a4a53ce09920 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sat, 20 Feb 2021 21:26:16 +0100 Subject: [PATCH 17/96] ingredients and helpers --- cookbook/helper/dal.py | 2 +- cookbook/helper/recipe_url_import.py | 10 +++++----- cookbook/integration/chowdown.py | 8 ++++---- cookbook/integration/integration.py | 2 +- cookbook/integration/mealie.py | 6 +++--- cookbook/integration/nextcloud_cookbook.py | 6 +++--- cookbook/integration/paprika.py | 8 ++++---- cookbook/integration/safron.py | 6 +++--- cookbook/tests/other/test_edits_recipe.py | 2 +- 9 files changed, 25 insertions(+), 25 deletions(-) diff --git a/cookbook/helper/dal.py b/cookbook/helper/dal.py index 6a109a6d..879279c8 100644 --- a/cookbook/helper/dal.py +++ b/cookbook/helper/dal.py @@ -10,7 +10,7 @@ class BaseAutocomplete(autocomplete.Select2QuerySetView): if not self.request.user.is_authenticated: return self.model.objects.none() - qs = self.model.objects.all() + qs = self.model.objects.filter(space=self.request.space).all() if self.q: qs = qs.filter(name__icontains=self.q) diff --git a/cookbook/helper/recipe_url_import.py b/cookbook/helper/recipe_url_import.py index 0ff4f1c9..78104ca3 100644 --- a/cookbook/helper/recipe_url_import.py +++ b/cookbook/helper/recipe_url_import.py @@ -12,7 +12,7 @@ from django.utils.dateparse import parse_duration from django.utils.translation import gettext as _ -def get_from_html(html_text, url): +def get_from_html(html_text, url, space): soup = BeautifulSoup(html_text, "html.parser") # first try finding ld+json as its most common @@ -31,7 +31,7 @@ def get_from_html(html_text, url): if ('@type' in ld_json_item and ld_json_item['@type'] == 'Recipe'): - return JsonResponse(find_recipe_json(ld_json_item, url)) + return JsonResponse(find_recipe_json(ld_json_item, url, space)) except JSONDecodeError: return JsonResponse( { @@ -45,7 +45,7 @@ def get_from_html(html_text, url): for i in items: md_json = json.loads(i.json()) if 'schema.org/Recipe' in str(md_json['type']): - return JsonResponse(find_recipe_json(md_json['properties'], url)) + return JsonResponse(find_recipe_json(md_json['properties'], url, space)) return JsonResponse( { @@ -55,7 +55,7 @@ def get_from_html(html_text, url): status=400) -def find_recipe_json(ld_json, url): +def find_recipe_json(ld_json, url, space): if type(ld_json['name']) == list: try: ld_json['name'] = ld_json['name'][0] @@ -136,7 +136,7 @@ def find_recipe_json(ld_json, url): # keywords as list for kw in ld_json['keywords']: - if k := Keyword.objects.filter(name=kw).first(): + if k := Keyword.objects.filter(name=kw, space=space).first(): keywords.append({'id': str(k.id), 'text': str(k).strip()}) else: keywords.append({'id': random.randrange(1111111, 9999999, 1), 'text': kw.strip()}) diff --git a/cookbook/integration/chowdown.py b/cookbook/integration/chowdown.py index f7a21b5b..8ce74189 100644 --- a/cookbook/integration/chowdown.py +++ b/cookbook/integration/chowdown.py @@ -47,10 +47,10 @@ class Chowdown(Integration): if description_mode and len(line) > 3 and '---' not in line: descriptions.append(line) - recipe = Recipe.objects.create(name=title, created_by=self.request.user, internal=True, ) + recipe = Recipe.objects.create(name=title, created_by=self.request.user, internal=True, space=self.request.space) for k in tags.split(','): - keyword, created = Keyword.objects.get_or_create(name=k.strip()) + keyword, created = Keyword.objects.get_or_create(name=k.strip(), space=self.request.space) recipe.keywords.add(keyword) step = Step.objects.create( @@ -59,8 +59,8 @@ class Chowdown(Integration): for ingredient in ingredients: amount, unit, ingredient, note = parse(ingredient) - f, created = Food.objects.get_or_create(name=ingredient) - u, created = Unit.objects.get_or_create(name=unit) + f, created = Food.objects.get_or_create(name=ingredient, space=self.request.space) + u, created = Unit.objects.get_or_create(name=unit, space=self.request.space) step.ingredients.add(Ingredient.objects.create( food=f, unit=u, amount=amount, note=note )) diff --git a/cookbook/integration/integration.py b/cookbook/integration/integration.py index 89c4af01..49329e41 100644 --- a/cookbook/integration/integration.py +++ b/cookbook/integration/integration.py @@ -40,7 +40,7 @@ class Integration: export_zip_obj = ZipFile(export_zip_stream, 'w') for r in recipes: - if r.internal: + if r.internal and r.space == self.request.space: recipe_zip_stream = BytesIO() recipe_zip_obj = ZipFile(recipe_zip_stream, 'w') diff --git a/cookbook/integration/mealie.py b/cookbook/integration/mealie.py index 8099f665..2cce3163 100644 --- a/cookbook/integration/mealie.py +++ b/cookbook/integration/mealie.py @@ -18,7 +18,7 @@ class Mealie(Integration): recipe = Recipe.objects.create( name=recipe_json['name'].strip(), description=recipe_json['description'].strip(), - created_by=self.request.user, internal=True) + created_by=self.request.user, internal=True, space=self.request.space) # TODO parse times (given in PT2H3M ) @@ -32,8 +32,8 @@ class Mealie(Integration): for ingredient in recipe_json['recipeIngredient']: amount, unit, ingredient, note = parse(ingredient) - f, created = Food.objects.get_or_create(name=ingredient) - u, created = Unit.objects.get_or_create(name=unit) + f, created = Food.objects.get_or_create(name=ingredient, space=self.request.space) + u, created = Unit.objects.get_or_create(name=unit, space=self.request.space) step.ingredients.add(Ingredient.objects.create( food=f, unit=u, amount=amount, note=note )) diff --git a/cookbook/integration/nextcloud_cookbook.py b/cookbook/integration/nextcloud_cookbook.py index 47580e1a..8d43dc9d 100644 --- a/cookbook/integration/nextcloud_cookbook.py +++ b/cookbook/integration/nextcloud_cookbook.py @@ -19,7 +19,7 @@ class NextcloudCookbook(Integration): recipe = Recipe.objects.create( name=recipe_json['name'].strip(), description=recipe_json['description'].strip(), created_by=self.request.user, internal=True, - servings=recipe_json['recipeYield']) + servings=recipe_json['recipeYield'], space=self.request.space) # TODO parse times (given in PT2H3M ) # TODO parse keywords @@ -34,8 +34,8 @@ class NextcloudCookbook(Integration): for ingredient in recipe_json['recipeIngredient']: amount, unit, ingredient, note = parse(ingredient) - f, created = Food.objects.get_or_create(name=ingredient) - u, created = Unit.objects.get_or_create(name=unit) + f, created = Food.objects.get_or_create(name=ingredient, space=self.request.space) + u, created = Unit.objects.get_or_create(name=unit, space=self.request.space) step.ingredients.add(Ingredient.objects.create( food=f, unit=u, amount=amount, note=note )) diff --git a/cookbook/integration/paprika.py b/cookbook/integration/paprika.py index 520c90b6..596b0ba2 100644 --- a/cookbook/integration/paprika.py +++ b/cookbook/integration/paprika.py @@ -27,15 +27,15 @@ class Paprika(Integration): for i in items: md_json = json.loads(i.json()) if 'schema.org/Recipe' in str(md_json['type']): - recipe_json = find_recipe_json(md_json['properties'], '') - recipe = Recipe.objects.create(name=recipe_json['name'].strip(), created_by=self.request.user, internal=True) + recipe_json = find_recipe_json(md_json['properties'], '', space=self.request.space) + recipe = Recipe.objects.create(name=recipe_json['name'].strip(), created_by=self.request.user, internal=True, space=self.request.space) step = Step.objects.create( instruction=recipe_json['recipeInstructions'] ) for ingredient in recipe_json['recipeIngredient']: - f, created = Food.objects.get_or_create(name=ingredient['ingredient']['text']) - u, created = Unit.objects.get_or_create(name=ingredient['unit']['text']) + f, created = Food.objects.get_or_create(name=ingredient['ingredient']['text'], space=self.request.space) + u, created = Unit.objects.get_or_create(name=ingredient['unit']['text'], space=self.request.space) step.ingredients.add(Ingredient.objects.create( food=f, unit=u, amount=ingredient['amount'], note=ingredient['note'] )) diff --git a/cookbook/integration/safron.py b/cookbook/integration/safron.py index 77277950..c2cb90aa 100644 --- a/cookbook/integration/safron.py +++ b/cookbook/integration/safron.py @@ -41,14 +41,14 @@ class Safron(Integration): ingredient_mode = False direction_mode = True - recipe = Recipe.objects.create(name=title, description=description, created_by=self.request.user, internal=True, ) + recipe = Recipe.objects.create(name=title, description=description, created_by=self.request.user, internal=True, space=self.request.space, ) step = Step.objects.create(instruction='\n'.join(directions)) for ingredient in ingredients: amount, unit, ingredient, note = parse(ingredient) - f, created = Food.objects.get_or_create(name=ingredient) - u, created = Unit.objects.get_or_create(name=unit) + f, created = Food.objects.get_or_create(name=ingredient, space=self.request.space) + u, created = Unit.objects.get_or_create(name=unit, space=self.request.space) step.ingredients.add(Ingredient.objects.create( food=f, unit=u, amount=amount, note=note )) diff --git a/cookbook/tests/other/test_edits_recipe.py b/cookbook/tests/other/test_edits_recipe.py index 7394854c..19d73e50 100644 --- a/cookbook/tests/other/test_edits_recipe.py +++ b/cookbook/tests/other/test_edits_recipe.py @@ -25,7 +25,7 @@ class TestEditsRecipe(TestBase): for test in test_list: with open(test['file'], 'rb') as file: print(f'Testing {test["file"]} expecting length {test["result_length"]}') - parsed_content = json.loads(get_from_html(file.read(), 'test_url').content) + parsed_content = json.loads(get_from_html(file.read(), 'test_url', None).content) self.assertEqual(len(str(parsed_content)), test['result_length']) file.close() From 58c6077925f2213d09afc1fd63f4e52feef07428 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sat, 20 Feb 2021 22:56:29 +0100 Subject: [PATCH 18/96] basic test stuff --- cookbook/tests/api/test_api_cook_log.py | 0 cookbook/tests/api/test_api_ingredient.py | 0 cookbook/tests/api/test_api_meal_plan.py | 0 cookbook/tests/api/test_api_meal_type.py | 0 cookbook/tests/api/test_api_recipe_book.py | 0 .../tests/api/test_api_recipe_book_entry.py | 0 ..._shopping.py => test_api_shopping_list.py} | 0 .../tests/api/test_api_shopping_list_entry.py | 0 .../api/test_api_shopping_list_recipe.py | 0 cookbook/tests/api/test_api_step.py | 0 cookbook/tests/api/test_api_supermarket.py | 0 ...st_api_syn_log.py => test_api_sync_log.py} | 0 cookbook/tests/api/test_api_view_log.py | 0 cookbook/tests/test_setup.py | 53 +++++++++++++------ cookbook/views/api.py | 4 ++ 15 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 cookbook/tests/api/test_api_cook_log.py create mode 100644 cookbook/tests/api/test_api_ingredient.py create mode 100644 cookbook/tests/api/test_api_meal_plan.py create mode 100644 cookbook/tests/api/test_api_meal_type.py create mode 100644 cookbook/tests/api/test_api_recipe_book.py create mode 100644 cookbook/tests/api/test_api_recipe_book_entry.py rename cookbook/tests/api/{test_api_shopping.py => test_api_shopping_list.py} (100%) create mode 100644 cookbook/tests/api/test_api_shopping_list_entry.py create mode 100644 cookbook/tests/api/test_api_shopping_list_recipe.py create mode 100644 cookbook/tests/api/test_api_step.py create mode 100644 cookbook/tests/api/test_api_supermarket.py rename cookbook/tests/api/{test_api_syn_log.py => test_api_sync_log.py} (100%) create mode 100644 cookbook/tests/api/test_api_view_log.py diff --git a/cookbook/tests/api/test_api_cook_log.py b/cookbook/tests/api/test_api_cook_log.py new file mode 100644 index 00000000..e69de29b diff --git a/cookbook/tests/api/test_api_ingredient.py b/cookbook/tests/api/test_api_ingredient.py new file mode 100644 index 00000000..e69de29b diff --git a/cookbook/tests/api/test_api_meal_plan.py b/cookbook/tests/api/test_api_meal_plan.py new file mode 100644 index 00000000..e69de29b diff --git a/cookbook/tests/api/test_api_meal_type.py b/cookbook/tests/api/test_api_meal_type.py new file mode 100644 index 00000000..e69de29b diff --git a/cookbook/tests/api/test_api_recipe_book.py b/cookbook/tests/api/test_api_recipe_book.py new file mode 100644 index 00000000..e69de29b diff --git a/cookbook/tests/api/test_api_recipe_book_entry.py b/cookbook/tests/api/test_api_recipe_book_entry.py new file mode 100644 index 00000000..e69de29b diff --git a/cookbook/tests/api/test_api_shopping.py b/cookbook/tests/api/test_api_shopping_list.py similarity index 100% rename from cookbook/tests/api/test_api_shopping.py rename to cookbook/tests/api/test_api_shopping_list.py diff --git a/cookbook/tests/api/test_api_shopping_list_entry.py b/cookbook/tests/api/test_api_shopping_list_entry.py new file mode 100644 index 00000000..e69de29b diff --git a/cookbook/tests/api/test_api_shopping_list_recipe.py b/cookbook/tests/api/test_api_shopping_list_recipe.py new file mode 100644 index 00000000..e69de29b diff --git a/cookbook/tests/api/test_api_step.py b/cookbook/tests/api/test_api_step.py new file mode 100644 index 00000000..e69de29b diff --git a/cookbook/tests/api/test_api_supermarket.py b/cookbook/tests/api/test_api_supermarket.py new file mode 100644 index 00000000..e69de29b diff --git a/cookbook/tests/api/test_api_syn_log.py b/cookbook/tests/api/test_api_sync_log.py similarity index 100% rename from cookbook/tests/api/test_api_syn_log.py rename to cookbook/tests/api/test_api_sync_log.py diff --git a/cookbook/tests/api/test_api_view_log.py b/cookbook/tests/api/test_api_view_log.py new file mode 100644 index 00000000..e69de29b diff --git a/cookbook/tests/test_setup.py b/cookbook/tests/test_setup.py index 7f9ba59c..a540b66a 100644 --- a/cookbook/tests/test_setup.py +++ b/cookbook/tests/test_setup.py @@ -2,45 +2,64 @@ from django.contrib import auth from django.contrib.auth.models import Group, User from django.test import Client, TestCase +from cookbook.models import Space + class TestBase(TestCase): + superuser_client = None + anonymous_client = None + + guest_client_1 = None + guest_client_2 = None user_client_1 = None user_client_2 = None admin_client_1 = None admin_client_2 = None - guest_client_1 = None - guest_client_2 = None - superuser_client = None - anonymous_client = None - def create_login_user(self, name, group): + s2_guest_client_1 = None + s2_user_client_1 = None + s2_admin_client_1 = None + s2_superuser_client = None + + def create_login_user(self, name, group, space, superuser=False): client = Client() setattr(self, name, client) client.force_login(User.objects.get_or_create(username=name)[0]) user = auth.get_user(getattr(self, name)) user.groups.add(Group.objects.get(name=group)) self.assertTrue(user.is_authenticated) + if superuser: + user.is_superuser = True + + user.userpreference.space = space + user.save() return user def setUp(self): - self.create_login_user('admin_client_1', 'admin') - self.create_login_user('admin_client_2', 'admin') + # users for space 1 + space_1 = Space.objects.create(name='space 1') - self.create_login_user('user_client_1', 'user') - self.create_login_user('user_client_2', 'user') + self.create_login_user('admin_client_1', 'admin', space_1) + self.create_login_user('admin_client_2', 'admin', space_1) - self.create_login_user('guest_client_1', 'guest') - self.create_login_user('guest_client_2', 'guest') + self.create_login_user('user_client_1', 'user', space_1) + self.create_login_user('user_client_2', 'user', space_1) + + self.create_login_user('guest_client_1', 'guest', space_1) + self.create_login_user('guest_client_2', 'guest', space_1) self.anonymous_client = Client() - user = self.create_login_user('superuser_client', 'admin') - user.is_superuser = True - user.save() + self.create_login_user('superuser_client', 'admin', space_1, superuser=True) - def batch_requests( - self, clients, url, method='get', payload={}, content_type='' - ): + # users for space 2 + space_2 = Space.objects.create(name='space 2') + self.create_login_user('s2_admin_client_1', 'admin', space_2) + self.create_login_user('s2_user_client_1', 'user', space_2) + self.create_login_user('s2_guest_client_1', 'guest', space_2) + self.create_login_user('s2_superuser_client', 'admin', space_2, superuser=True) + + def batch_requests(self, clients, url, method='get', payload={}, content_type=''): for c in clients: if method == 'get': r = c[0].get(url) diff --git a/cookbook/views/api.py b/cookbook/views/api.py index eb111b50..a4add1cc 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -312,6 +312,10 @@ class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin): ) def image(self, request, pk): obj = self.get_object() + + if obj.get_space() != request.space: + raise PermissionDenied(detail='You do not have the required permission to perform this action', code=403) + serializer = self.serializer_class( obj, data=request.data, partial=True ) From beb4aa634f205bfb94187d790f917693e3115366 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sat, 20 Feb 2021 23:42:44 +0100 Subject: [PATCH 19/96] forms --- cookbook/forms.py | 85 ++++++++++++++++++++++++----- cookbook/helper/scope_middleware.py | 4 +- cookbook/views/data.py | 4 +- cookbook/views/edit.py | 45 ++++++++------- cookbook/views/import_export.py | 6 +- cookbook/views/new.py | 9 +-- cookbook/views/views.py | 2 +- 7 files changed, 107 insertions(+), 48 deletions(-) diff --git a/cookbook/forms.py b/cookbook/forms.py index 6d8d5dba..1e68f42c 100644 --- a/cookbook/forms.py +++ b/cookbook/forms.py @@ -6,7 +6,7 @@ from emoji_picker.widgets import EmojiPickerTextInput from .models import (Comment, Food, InviteLink, Keyword, MealPlan, Recipe, RecipeBook, RecipeBookEntry, Storage, Sync, Unit, User, - UserPreference) + UserPreference, SupermarketCategory, MealType) class SelectWidget(widgets.Select): @@ -77,11 +77,16 @@ class ExternalRecipeForm(forms.ModelForm): file_path = forms.CharField(disabled=True, required=False) file_uid = forms.CharField(disabled=True, required=False) + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['keywords'].queryset = Keyword.objects.filter(space=space).all() + class Meta: model = Recipe fields = ( 'name', 'description', 'servings', 'working_time', 'waiting_time', - 'file_path', 'file_uid' + 'file_path', 'file_uid', 'keywords' ) labels = { @@ -92,7 +97,10 @@ class ExternalRecipeForm(forms.ModelForm): 'file_path': _('Path'), 'file_uid': _('Storage UID'), } - # widgets = {'keywords': MultiSelectWidget} + widgets = {'keywords': MultiSelectWidget} + field_classes = { + 'keywords': SafeModelMultipleChoiceField, + } class ImportExportBase(forms.Form): @@ -114,12 +122,12 @@ class ImportForm(ImportExportBase): class ExportForm(ImportExportBase): - recipes = forms.ModelMultipleChoiceField(widget=MultiSelectWidget, queryset=None) + recipes = forms.ModelMultipleChoiceField(widget=MultiSelectWidget, queryset=Recipe.objects.none()) def __init__(self, *args, **kwargs): - super().__init__() - user = kwargs.pop('user') - self.fields['recipes'].queryset = Recipe.objects.filter(internal=True).filter(space=user.userpreference.space).all() + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['recipes'].queryset = Recipe.objects.filter(space=space).all() class UnitMergeForm(forms.Form): @@ -138,8 +146,12 @@ class UnitMergeForm(forms.Form): help_text=_('Unit that should be replaced.'), ) + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['new_unit'].queryset = Unit.objects.filter(space=space).all() + self.fields['old_unit'].queryset = Unit.objects.filter(space=space).all() -# todo spaces form here on class FoodMergeForm(forms.Form): prefix = 'food' @@ -157,6 +169,12 @@ class FoodMergeForm(forms.Form): help_text=_('Food that should be replaced.'), ) + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['new_food'].queryset = Food.objects.filter(space=space).all() + self.fields['old_food'].queryset = Food.objects.filter(space=space).all() + class CommentForm(forms.ModelForm): prefix = 'comment' @@ -181,6 +199,13 @@ class KeywordForm(forms.ModelForm): class FoodForm(forms.ModelForm): + + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['recipe'].queryset = Recipe.objects.filter(space=space).all() + self.fields['supermarket_category'].queryset = SupermarketCategory.objects.filter(space=space).all() + class Meta: model = Food fields = ('name', 'description', 'ignore_shopping', 'recipe', 'supermarket_category') @@ -198,18 +223,16 @@ class StorageForm(forms.ModelForm): required=False ) password = forms.CharField( - widget=forms.TextInput( - attrs={'autocomplete': 'new-password', 'type': 'password'} - ), + widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}), required=False, - help_text=_('Leave empty for dropbox and enter app password for nextcloud.') # noqa: E501 + help_text=_('Leave empty for dropbox and enter app password for nextcloud.') ) token = forms.CharField( widget=forms.TextInput( attrs={'autocomplete': 'new-password', 'type': 'password'} ), required=False, - help_text=_('Leave empty for nextcloud and enter api token for dropbox.') # noqa: E501 + help_text=_('Leave empty for nextcloud and enter api token for dropbox.') ) class Meta: @@ -217,13 +240,18 @@ class StorageForm(forms.ModelForm): fields = ('name', 'method', 'username', 'password', 'token', 'url', 'path') help_texts = { - 'url': _('Leave empty for dropbox and enter only base url for nextcloud (/remote.php/webdav/ is added automatically)'), # noqa: E501 + 'url': _('Leave empty for dropbox and enter only base url for nextcloud (/remote.php/webdav/ is added automatically)'), } class RecipeBookEntryForm(forms.ModelForm): prefix = 'bookmark' + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['book'].queryset = RecipeBook.objects.filter(space=space).all() + class Meta: model = RecipeBookEntry fields = ('book',) @@ -234,6 +262,12 @@ class RecipeBookEntryForm(forms.ModelForm): class SyncForm(forms.ModelForm): + + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['book'].queryset = Storage.objects.filter(space=space).all() + class Meta: model = Sync fields = ('storage', 'path', 'active') @@ -246,13 +280,23 @@ class SyncForm(forms.ModelForm): class BatchEditForm(forms.Form): search = forms.CharField(label=_('Search String')) keywords = forms.ModelMultipleChoiceField( - queryset=Keyword.objects.none().order_by('id'), + queryset=Keyword.objects.none(), required=False, widget=MultiSelectWidget ) + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['keywords'].queryset = Keyword.objects.filter(space=space).all().order_by('id') + class ImportRecipeForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['keywords'].queryset = Keyword.objects.filter(space=space).all() + class Meta: model = Recipe fields = ('name', 'keywords', 'file_path', 'file_uid') @@ -270,6 +314,11 @@ class ImportRecipeForm(forms.ModelForm): class RecipeBookForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['shared'].queryset = User.objects.filter(userpreference__space=space).all() + class Meta: model = RecipeBook fields = ('name', 'icon', 'description', 'shared') @@ -280,6 +329,12 @@ class RecipeBookForm(forms.ModelForm): class MealPlanForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(*args, **kwargs) + self.fields['recipe'].queryset = Recipe.objects.filter(space=space).all() + self.fields['meal_type'].queryset = MealType.objects.filter(space=space).all() + self.fields['shared'].queryset = User.objects.filter(userpreference__space=space).all() def clean(self): cleaned_data = super(MealPlanForm, self).clean() diff --git a/cookbook/helper/scope_middleware.py b/cookbook/helper/scope_middleware.py index 0bf415b8..2ec472f4 100644 --- a/cookbook/helper/scope_middleware.py +++ b/cookbook/helper/scope_middleware.py @@ -9,8 +9,8 @@ class ScopeMiddleware: if request.user.is_authenticated: request.space = request.user.userpreference.space - #with scopes_disabled(): - with scope(space=request.space): + with scopes_disabled(): + #with scope(space=request.space): return self.get_response(request) else: return self.get_response(request) diff --git a/cookbook/views/data.py b/cookbook/views/data.py index 77081e5f..39218e6f 100644 --- a/cookbook/views/data.py +++ b/cookbook/views/data.py @@ -73,7 +73,7 @@ def batch_import(request): @group_required('user') def batch_edit(request): if request.method == "POST": - form = BatchEditForm(request.POST) + form = BatchEditForm(request.POST, space=request.space) if form.is_valid(): word = form.cleaned_data['search'] keywords = form.cleaned_data['keywords'] @@ -100,7 +100,7 @@ def batch_edit(request): return redirect('data_batch_edit') else: - form = BatchEditForm() + form = BatchEditForm(space=request.space) return render(request, 'batch/edit.html', {'form': form}) diff --git a/cookbook/views/edit.py b/cookbook/views/edit.py index e1913a9a..3ce02087 100644 --- a/cookbook/views/edit.py +++ b/cookbook/views/edit.py @@ -6,6 +6,7 @@ from django.shortcuts import get_object_or_404, render from django.urls import reverse, reverse_lazy from django.utils.translation import gettext as _ from django.views.generic import UpdateView +from django.views.generic.edit import FormMixin from django_scopes import scopes_disabled from cookbook.forms import (CommentForm, ExternalRecipeForm, FoodForm, @@ -51,7 +52,15 @@ def internal_recipe_update(request, pk): ) -class SyncUpdate(GroupRequiredMixin, UpdateView): +class SpaceFormMixing(FormMixin): + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + kwargs.update({'space': self.request.space}) + return kwargs + + +class SyncUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing): groups_required = ['admin'] template_name = "generic/edit_template.html" model = Sync @@ -85,7 +94,7 @@ class KeywordUpdate(GroupRequiredMixin, UpdateView): return context -class FoodUpdate(GroupRequiredMixin, UpdateView): +class FoodUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing): groups_required = ['user'] template_name = "generic/edit_template.html" model = Food @@ -182,7 +191,7 @@ class ImportUpdate(GroupRequiredMixin, UpdateView): return context -class RecipeBookUpdate(OwnerRequiredMixin, UpdateView): +class RecipeBookUpdate(OwnerRequiredMixin, UpdateView, SpaceFormMixing): template_name = "generic/edit_template.html" model = RecipeBook form_class = RecipeBookForm @@ -196,7 +205,7 @@ class RecipeBookUpdate(OwnerRequiredMixin, UpdateView): return context -class MealPlanUpdate(OwnerRequiredMixin, UpdateView): +class MealPlanUpdate(OwnerRequiredMixin, UpdateView, SpaceFormMixing): template_name = "generic/edit_template.html" model = MealPlan form_class = MealPlanForm @@ -216,7 +225,7 @@ class MealPlanUpdate(OwnerRequiredMixin, UpdateView): return context -class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView): +class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing): groups_required = ['user'] model = Recipe form_class = ExternalRecipeForm @@ -226,8 +235,8 @@ class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView): self.object = form.save(commit=False) old_recipe = Recipe.objects.get(pk=self.object.pk, space=self.request.space) if not old_recipe.name == self.object.name: + # TODO central location to handle storage type switches if self.object.storage.method == Storage.DROPBOX: - # TODO central location to handle storage type switches Dropbox.rename_file(old_recipe, self.object.name) if self.object.storage.method == Storage.NEXTCLOUD: Nextcloud.rename_file(old_recipe, self.object.name) @@ -240,24 +249,18 @@ class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView): os.path.splitext(self.object.file_path)[1] ) - messages.add_message( - self.request, messages.SUCCESS, _('Changes saved!') - ) + messages.add_message(self.request, messages.SUCCESS, _('Changes saved!')) return super(ExternalRecipeUpdate, self).form_valid(form) def form_invalid(self, form): - messages.add_message( - self.request, - messages.ERROR, - _('Error saving changes!') - ) + messages.add_message(self.request, messages.ERROR, _('Error saving changes!')) return super(ExternalRecipeUpdate, self).form_valid(form) def get_success_url(self): return reverse('edit_recipe', kwargs={'pk': self.object.pk}) def get_context_data(self, **kwargs): - context = super(ExternalRecipeUpdate, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) context['title'] = _("Recipe") context['view_url'] = reverse('view_recipe', args=[self.object.pk]) if self.object.storage: @@ -271,7 +274,7 @@ class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView): def edit_ingredients(request): if request.method == "POST": success = False - units_form = UnitMergeForm(request.POST, prefix=UnitMergeForm.prefix) + units_form = UnitMergeForm(request.POST, prefix=UnitMergeForm.prefix, space=request.space) if units_form.is_valid(): new_unit = units_form.cleaned_data['new_unit'] old_unit = units_form.cleaned_data['old_unit'] @@ -287,7 +290,7 @@ def edit_ingredients(request): else: messages.add_message(request, messages.ERROR, _('Cannot merge with the same object!')) - food_form = FoodMergeForm(request.POST, prefix=FoodMergeForm.prefix) + food_form = FoodMergeForm(request.POST, prefix=FoodMergeForm.prefix, space=request.space) if food_form.is_valid(): new_food = food_form.cleaned_data['new_food'] old_food = food_form.cleaned_data['old_food'] @@ -304,10 +307,10 @@ def edit_ingredients(request): messages.add_message(request, messages.ERROR, _('Cannot merge with the same object!')) if success: - units_form = UnitMergeForm() - food_form = FoodMergeForm() + units_form = UnitMergeForm(space=request.space) + food_form = FoodMergeForm(space=request.space) else: - units_form = UnitMergeForm() - food_form = FoodMergeForm() + units_form = UnitMergeForm(space=request.space) + food_form = FoodMergeForm(space=request.space) return render(request, 'forms/ingredients.html', {'units_form': units_form, 'food_form': food_form}) diff --git a/cookbook/views/import_export.py b/cookbook/views/import_export.py index d7ea9de0..bf3f7c76 100644 --- a/cookbook/views/import_export.py +++ b/cookbook/views/import_export.py @@ -49,7 +49,7 @@ def import_recipe(request): @group_required('user') def export_recipe(request): if request.method == "POST": - form = ExportForm(request.POST, user=request.user) + form = ExportForm(request.POST, space=request.space) if form.is_valid(): try: integration = get_integration(request, form.cleaned_data['type']) @@ -58,11 +58,11 @@ def export_recipe(request): messages.add_message(request, messages.ERROR, _('Exporting is not implemented for this provider')) else: - form = ExportForm(user=request.user) + form = ExportForm(space=request.space) recipe = request.GET.get('r') if recipe: if re.match(r'^([0-9])+$', recipe): if recipe := Recipe.objects.filter(pk=int(recipe), space=request.space).first(): - form = ExportForm(initial={'recipes': recipe}, user=request.user) + form = ExportForm(initial={'recipes': recipe}, space=request.space) return render(request, 'export.html', {'form': form}) diff --git a/cookbook/views/new.py b/cookbook/views/new.py index bdc2bac7..16acb992 100644 --- a/cookbook/views/new.py +++ b/cookbook/views/new.py @@ -14,6 +14,7 @@ from cookbook.helper.permission_helper import (GroupRequiredMixin, group_required) from cookbook.models import (InviteLink, Keyword, MealPlan, MealType, Recipe, RecipeBook, RecipeImport, ShareLink, Step) +from cookbook.views.edit import SpaceFormMixing class RecipeCreate(GroupRequiredMixin, CreateView): @@ -89,7 +90,7 @@ class StorageCreate(GroupRequiredMixin, CreateView): @group_required('user') def create_new_external_recipe(request, import_id): if request.method == "POST": - form = ImportRecipeForm(request.POST) + form = ImportRecipeForm(request.POST, space=request.space) if form.is_valid(): new_recipe = get_object_or_404(RecipeImport, pk=import_id, space=request.space) recipe = Recipe() @@ -117,13 +118,13 @@ def create_new_external_recipe(request, import_id): 'file_path': new_recipe.file_path, 'name': new_recipe.name, 'file_uid': new_recipe.file_uid - } + }, space=request.space ) return render(request, 'forms/edit_import_recipe.html', {'form': form}) -class RecipeBookCreate(GroupRequiredMixin, CreateView): +class RecipeBookCreate(GroupRequiredMixin, CreateView, SpaceFormMixing): groups_required = ['user'] template_name = "generic/new_template.html" model = RecipeBook @@ -143,7 +144,7 @@ class RecipeBookCreate(GroupRequiredMixin, CreateView): return context -class MealPlanCreate(GroupRequiredMixin, CreateView): +class MealPlanCreate(GroupRequiredMixin, CreateView, SpaceFormMixing): groups_required = ['user'] template_name = "generic/new_template.html" model = MealPlan diff --git a/cookbook/views/views.py b/cookbook/views/views.py index a20da69c..d08e9a19 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -129,7 +129,7 @@ def recipe_view(request, pk, share=None): request, messages.SUCCESS, _('Comment saved!') ) - bookmark_form = RecipeBookEntryForm(request.POST, prefix='bookmark') + bookmark_form = RecipeBookEntryForm(request.POST, prefix='bookmark', space=request.space) if bookmark_form.is_valid(): bookmark = RecipeBookEntry() bookmark.recipe = recipe From 846c660811a06088bb2e260ad93b8a41044bff72 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sun, 21 Feb 2021 15:08:43 +0100 Subject: [PATCH 20/96] usr signup and more --- cookbook/admin.py | 18 ++- cookbook/forms.py | 12 +- cookbook/helper/permission_helper.py | 20 ++- cookbook/helper/scope_middleware.py | 17 ++- cookbook/integration/integration.py | 3 +- .../migrations/0109_auto_20210221_1204.py | 63 +++++++++ .../migrations/0110_auto_20210221_1406.py | 19 +++ cookbook/migrations/0111_space_created_by.py | 32 +++++ cookbook/models.py | 31 ++++- cookbook/serializer.py | 23 +--- cookbook/templates/no_groups_info.html | 2 +- cookbook/templates/no_space_info.html | 20 +++ cookbook/urls.py | 2 +- cookbook/views/new.py | 5 + cookbook/views/views.py | 126 ++++++++---------- 15 files changed, 287 insertions(+), 106 deletions(-) create mode 100644 cookbook/migrations/0109_auto_20210221_1204.py create mode 100644 cookbook/migrations/0110_auto_20210221_1406.py create mode 100644 cookbook/migrations/0111_space_created_by.py create mode 100644 cookbook/templates/no_space_info.html diff --git a/cookbook/admin.py b/cookbook/admin.py index 76af757a..8893a7a0 100644 --- a/cookbook/admin.py +++ b/cookbook/admin.py @@ -1,4 +1,6 @@ from django.contrib import admin +from django.contrib.auth.admin import UserAdmin +from django.contrib.auth.models import User, Group from .models import (Comment, CookLog, Food, Ingredient, InviteLink, Keyword, MealPlan, MealType, NutritionInformation, Recipe, @@ -8,6 +10,17 @@ from .models import (Comment, CookLog, Food, Ingredient, InviteLink, Keyword, ViewLog, Supermarket, SupermarketCategory, SupermarketCategoryRelation) +class CustomUserAdmin(UserAdmin): + def has_add_permission(self, request, obj=None): + return False + + +admin.site.unregister(User) +admin.site.register(User, CustomUserAdmin) + +admin.site.unregister(Group) + + class SpaceAdmin(admin.ModelAdmin): list_display = ('name', 'message') @@ -16,10 +29,7 @@ admin.site.register(Space, SpaceAdmin) class UserPreferenceAdmin(admin.ModelAdmin): - list_display = ( - 'name', 'theme', 'nav_color', - 'default_page', 'search_style', 'comments' - ) + list_display = ('name', 'space', 'theme', 'nav_color', 'default_page', 'search_style',) @staticmethod def name(obj): diff --git a/cookbook/forms.py b/cookbook/forms.py index 1e68f42c..73a80417 100644 --- a/cookbook/forms.py +++ b/cookbook/forms.py @@ -6,7 +6,7 @@ from emoji_picker.widgets import EmojiPickerTextInput from .models import (Comment, Food, InviteLink, Keyword, MealPlan, Recipe, RecipeBook, RecipeBookEntry, Storage, Sync, Unit, User, - UserPreference, SupermarketCategory, MealType) + UserPreference, SupermarketCategory, MealType, Space) class SelectWidget(widgets.Select): @@ -371,12 +371,20 @@ class MealPlanForm(forms.ModelForm): class InviteLinkForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + user = kwargs.pop('user') + super().__init__(*args, **kwargs) + self.fields['space'].queryset = Space.objects.filter(created_by=user).all() + class Meta: model = InviteLink - fields = ('username', 'group', 'valid_until') + fields = ('username', 'group', 'valid_until', 'space') help_texts = { 'username': _('A username is not required, if left blank the new user can choose one.') # noqa: E501 } + field_classes = { + 'space': SafeModelChoiceField, + } class UserCreateForm(forms.Form): diff --git a/cookbook/helper/permission_helper.py b/cookbook/helper/permission_helper.py index fa9e1200..ebd7d082 100644 --- a/cookbook/helper/permission_helper.py +++ b/cookbook/helper/permission_helper.py @@ -123,9 +123,13 @@ class GroupRequiredMixin(object): messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) return HttpResponseRedirect(reverse_lazy('index')) - if self.get_object().get_space() != request.space: - messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) - return HttpResponseRedirect(reverse_lazy('index')) + try: + obj = self.get_object() + if obj.get_space() != request.space: + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) + return HttpResponseRedirect(reverse_lazy('index')) + except AttributeError: + pass return super(GroupRequiredMixin, self).dispatch(request, *args, **kwargs) @@ -141,9 +145,13 @@ class OwnerRequiredMixin(object): messages.add_message(request, messages.ERROR, _('You cannot interact with this object as it is not owned by you!')) return HttpResponseRedirect(reverse('index')) - if self.get_object().get_space() != request.space: - messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) - return HttpResponseRedirect(reverse_lazy('index')) + try: + obj = self.get_object() + if obj.get_space() != request.space: + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) + return HttpResponseRedirect(reverse_lazy('index')) + except AttributeError: + pass return super(OwnerRequiredMixin, self).dispatch(request, *args, **kwargs) diff --git a/cookbook/helper/scope_middleware.py b/cookbook/helper/scope_middleware.py index 2ec472f4..9726d526 100644 --- a/cookbook/helper/scope_middleware.py +++ b/cookbook/helper/scope_middleware.py @@ -1,3 +1,5 @@ +from django.shortcuts import redirect +from django.urls import reverse from django_scopes import scope, scopes_disabled @@ -7,10 +9,21 @@ class ScopeMiddleware: def __call__(self, request): if request.user.is_authenticated: - request.space = request.user.userpreference.space + + if request.user.groups.count() == 0: + return redirect('view_no_group') with scopes_disabled(): - #with scope(space=request.space): + if request.user.userpreference.space is None and not reverse('view_no_space') in request.path and not reverse('account_logout') in request.path: + return redirect(reverse('view_no_space')) + + if request.path.startswith('/admin/'): + with scopes_disabled(): + return self.get_response(request) + + request.space = request.user.userpreference.space + # with scopes_disabled(): + with scope(space=request.space): return self.get_response(request) else: return self.get_response(request) diff --git a/cookbook/integration/integration.py b/cookbook/integration/integration.py index 49329e41..49200d54 100644 --- a/cookbook/integration/integration.py +++ b/cookbook/integration/integration.py @@ -27,7 +27,8 @@ class Integration: self.keyword = Keyword.objects.create( name=f'Import {date_format(datetime.datetime.now(), "DATETIME_FORMAT")}.{datetime.datetime.now().strftime("%S")}', description=f'Imported by {request.user.get_user_name()} at {date_format(datetime.datetime.now(), "DATETIME_FORMAT")}', - icon='📥' + icon='📥', + space=request.space ) def do_export(self, recipes): diff --git a/cookbook/migrations/0109_auto_20210221_1204.py b/cookbook/migrations/0109_auto_20210221_1204.py new file mode 100644 index 00000000..37308fa7 --- /dev/null +++ b/cookbook/migrations/0109_auto_20210221_1204.py @@ -0,0 +1,63 @@ +# Generated by Django 3.1.6 on 2021-02-21 11:04 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0108_auto_20210219_1410'), + ] + + operations = [ + migrations.RemoveField( + model_name='recipebookentry', + name='space', + ), + migrations.AlterField( + model_name='food', + name='name', + field=models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)]), + ), + migrations.AlterField( + model_name='keyword', + name='name', + field=models.CharField(max_length=64), + ), + migrations.AlterField( + model_name='supermarket', + name='name', + field=models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)]), + ), + migrations.AlterField( + model_name='supermarketcategory', + name='name', + field=models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)]), + ), + migrations.AlterField( + model_name='unit', + name='name', + field=models.CharField(max_length=128, validators=[django.core.validators.MinLengthValidator(1)]), + ), + migrations.AlterUniqueTogether( + name='food', + unique_together={('space', 'name')}, + ), + migrations.AlterUniqueTogether( + name='keyword', + unique_together={('space', 'name')}, + ), + migrations.AlterUniqueTogether( + name='supermarket', + unique_together={('space', 'name')}, + ), + migrations.AlterUniqueTogether( + name='supermarketcategory', + unique_together={('space', 'name')}, + ), + migrations.AlterUniqueTogether( + name='unit', + unique_together={('space', 'name')}, + ), + ] diff --git a/cookbook/migrations/0110_auto_20210221_1406.py b/cookbook/migrations/0110_auto_20210221_1406.py new file mode 100644 index 00000000..47e002ff --- /dev/null +++ b/cookbook/migrations/0110_auto_20210221_1406.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1.6 on 2021-02-21 13:06 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0109_auto_20210221_1204'), + ] + + operations = [ + migrations.AlterField( + model_name='userpreference', + name='space', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.space'), + ), + ] diff --git a/cookbook/migrations/0111_space_created_by.py b/cookbook/migrations/0111_space_created_by.py new file mode 100644 index 00000000..7f42a74e --- /dev/null +++ b/cookbook/migrations/0111_space_created_by.py @@ -0,0 +1,32 @@ +# Generated by Django 3.1.6 on 2021-02-21 13:19 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +from django_scopes import scopes_disabled + + +def set_default_owner(apps, schema_editor): + Space = apps.get_model('cookbook', 'Space') + User = apps.get_model('auth', 'user') + + with scopes_disabled(): + for x in Space.objects.all(): + x.created_by = User.objects.filter(is_superuser=True).first() + x.save() + + +class Migration(migrations.Migration): + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('cookbook', '0110_auto_20210221_1406'), + ] + + operations = [ + migrations.AddField( + model_name='space', + name='created_by', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL), + ), + migrations.RunPython(set_default_owner), + ] diff --git a/cookbook/models.py b/cookbook/models.py index dd3b1098..e89e7745 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -45,8 +45,12 @@ class PermissionModelMixin: class Space(models.Model): name = models.CharField(max_length=128, default='Default') + created_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True) message = models.CharField(max_length=512, default='', blank=True) + def __str__(self): + return self.name + class UserPreference(models.Model, PermissionModelMixin): # Themes @@ -121,7 +125,7 @@ class UserPreference(models.Model, PermissionModelMixin): shopping_auto_sync = models.IntegerField(default=5) sticky_navbar = models.BooleanField(default=STICKY_NAV_PREF_DEFAULT) - space = models.ForeignKey(Space, on_delete=models.CASCADE) + space = models.ForeignKey(Space, on_delete=models.CASCADE, null=True) objects = ScopedManager(space='space') def __str__(self): @@ -168,7 +172,7 @@ class Sync(models.Model, PermissionModelMixin): class SupermarketCategory(models.Model, PermissionModelMixin): - name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) + name = models.CharField(max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) space = models.ForeignKey(Space, on_delete=models.CASCADE) @@ -177,9 +181,12 @@ class SupermarketCategory(models.Model, PermissionModelMixin): def __str__(self): return self.name + class Meta: + unique_together = (('space', 'name'),) + class Supermarket(models.Model, PermissionModelMixin): - name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) + name = models.CharField(max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) categories = models.ManyToManyField(SupermarketCategory, through='SupermarketCategoryRelation') @@ -189,6 +196,9 @@ class Supermarket(models.Model, PermissionModelMixin): def __str__(self): return self.name + class Meta: + unique_together = (('space', 'name'),) + class SupermarketCategoryRelation(models.Model, PermissionModelMixin): supermarket = models.ForeignKey(Supermarket, on_delete=models.CASCADE, related_name='category_to_supermarket') @@ -218,7 +228,7 @@ class SyncLog(models.Model, PermissionModelMixin): class Keyword(models.Model, PermissionModelMixin): - name = models.CharField(max_length=64, unique=True) + name = models.CharField(max_length=64) icon = models.CharField(max_length=16, blank=True, null=True) description = models.TextField(default="", blank=True) created_at = models.DateTimeField(auto_now_add=True) @@ -233,9 +243,12 @@ class Keyword(models.Model, PermissionModelMixin): else: return f"{self.name}" + class Meta: + unique_together = (('space', 'name'),) + class Unit(models.Model, PermissionModelMixin): - name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) + name = models.CharField(max_length=128, validators=[MinLengthValidator(1)]) description = models.TextField(blank=True, null=True) space = models.ForeignKey(Space, on_delete=models.CASCADE) @@ -244,9 +257,12 @@ class Unit(models.Model, PermissionModelMixin): def __str__(self): return self.name + class Meta: + unique_together = (('space', 'name'),) + class Food(models.Model, PermissionModelMixin): - name = models.CharField(unique=True, max_length=128, validators=[MinLengthValidator(1)]) + name = models.CharField(max_length=128, validators=[MinLengthValidator(1)]) recipe = models.ForeignKey('Recipe', null=True, blank=True, on_delete=models.SET_NULL) supermarket_category = models.ForeignKey(SupermarketCategory, null=True, blank=True, on_delete=models.SET_NULL) ignore_shopping = models.BooleanField(default=False) @@ -258,6 +274,9 @@ class Food(models.Model, PermissionModelMixin): def __str__(self): return self.name + class Meta: + unique_together = (('space', 'name'),) + class Ingredient(models.Model, PermissionModelMixin): food = models.ForeignKey(Food, on_delete=models.PROTECT, null=True, blank=True) diff --git a/cookbook/serializer.py b/cookbook/serializer.py index f52c2c92..436f849d 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -111,17 +111,12 @@ class KeywordSerializer(UniqueFieldsMixin, serializers.ModelSerializer): return str(obj) def create(self, validated_data): - # since multi select tags dont have id's - # duplicate names might be routed to create - obj, created = Keyword.objects.get_or_create(name=validated_data['name']) + obj, created = Keyword.objects.get_or_create(name=validated_data['name'], space=self.context['request'].space) return obj class Meta: model = Keyword - fields = ( - 'id', 'name', 'icon', 'label', 'description', - 'created_at', 'updated_at' - ) + fields = ('id', 'name', 'icon', 'label', 'description', 'created_at', 'updated_at') read_only_fields = ('id',) @@ -129,9 +124,7 @@ class KeywordSerializer(UniqueFieldsMixin, serializers.ModelSerializer): class UnitSerializer(UniqueFieldsMixin, serializers.ModelSerializer): def create(self, validated_data): - # since multi select tags dont have id's - # duplicate names might be routed to create - obj, created = Unit.objects.get_or_create(name=validated_data['name']) + obj, created = Unit.objects.get_or_create(name=validated_data['name'], space=self.context['request'].space) return obj class Meta: @@ -143,9 +136,7 @@ class UnitSerializer(UniqueFieldsMixin, serializers.ModelSerializer): class SupermarketCategorySerializer(UniqueFieldsMixin, WritableNestedModelSerializer): def create(self, validated_data): - # since multi select tags dont have id's - # duplicate names might be routed to create - obj, created = SupermarketCategory.objects.get_or_create(name=validated_data['name']) + obj, created = SupermarketCategory.objects.get_or_create(name=validated_data['name'], space=self.context['request'].space) return obj def update(self, instance, validated_data): @@ -176,9 +167,7 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer): supermarket_category = SupermarketCategorySerializer(allow_null=True, required=False) def create(self, validated_data): - # since multi select tags dont have id's - # duplicate names might be routed to create - obj, created = Food.objects.get_or_create(name=validated_data['name']) + obj, created = Food.objects.get_or_create(name=validated_data['name'], space=self.context['request'].space) return obj def update(self, instance, validated_data): @@ -256,6 +245,7 @@ class RecipeSerializer(WritableNestedModelSerializer): def create(self, validated_data): validated_data['created_by'] = self.context['request'].user + validated_data['space'] = self.context['request'].space return super().create(validated_data) @@ -455,4 +445,5 @@ class RecipeExportSerializer(WritableNestedModelSerializer): def create(self, validated_data): validated_data['created_by'] = self.context['request'].user + validated_data['space'] = self.context['request'].space return super().create(validated_data) diff --git a/cookbook/templates/no_groups_info.html b/cookbook/templates/no_groups_info.html index 53b5f04c..eac51be1 100644 --- a/cookbook/templates/no_groups_info.html +++ b/cookbook/templates/no_groups_info.html @@ -2,7 +2,7 @@ {% load static %} {% load i18n %} -{% block title %}{% trans "Offline" %}{% endblock %} +{% block title %}{% trans "No Permissions" %}{% endblock %} {% block content %} diff --git a/cookbook/templates/no_space_info.html b/cookbook/templates/no_space_info.html new file mode 100644 index 00000000..f8ad26e8 --- /dev/null +++ b/cookbook/templates/no_space_info.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} +{% load static %} +{% load i18n %} + +{% block title %}{% trans "No Space" %}{% endblock %} + + +{% block content %} + +
+ +

{% trans 'No Space' %}

+
+ + {% trans 'You are not a member of any space. Please contact your administrator.' %}
+ +
+ +{% endblock %} + diff --git a/cookbook/urls.py b/cookbook/urls.py index 08b3a834..c446a1b6 100644 --- a/cookbook/urls.py +++ b/cookbook/urls.py @@ -40,6 +40,7 @@ urlpatterns = [ path('', views.index, name='index'), path('setup/', views.setup, name='view_setup'), path('no-group', views.no_groups, name='view_no_group'), + path('no-space', views.no_space, name='view_no_space'), path('signup/', views.signup, name='view_signup'), path('system/', views.system, name='view_system'), path('search/', views.search, name='view_search'), @@ -105,7 +106,6 @@ urlpatterns = [ path('offline/', views.offline, name='view_offline'), - path('service-worker.js', (TemplateView.as_view(template_name="sw.js", content_type='application/javascript', )), name='service_worker'), path('manifest.json', (TemplateView.as_view(template_name="manifest.json", content_type='application/json', )), name='web_manifest'), ] diff --git a/cookbook/views/new.py b/cookbook/views/new.py index 16acb992..927c873c 100644 --- a/cookbook/views/new.py +++ b/cookbook/views/new.py @@ -212,3 +212,8 @@ class InviteLinkCreate(GroupRequiredMixin, CreateView): context = super(InviteLinkCreate, self).get_context_data(**kwargs) context['title'] = _("Invite Link") return context + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + kwargs.update({'user': self.request.user}) + return kwargs diff --git a/cookbook/views/views.py b/cookbook/views/views.py index d08e9a19..f781a766 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -26,7 +26,7 @@ from cookbook.forms import (CommentForm, Recipe, RecipeBookEntryForm, User, UserPreferenceForm) from cookbook.helper.permission_helper import group_required, share_link_valid, has_group_permission from cookbook.models import (Comment, CookLog, InviteLink, MealPlan, - RecipeBook, RecipeBookEntry, ViewLog, ShoppingList) + RecipeBook, RecipeBookEntry, ViewLog, ShoppingList, Space) from cookbook.tables import (CookLogTable, RecipeTable, RecipeTableSmall, ViewLogTable) from recipes.settings import DEMO @@ -92,6 +92,10 @@ def no_groups(request): return render(request, 'no_groups_info.html') +def no_space(request): + return render(request, 'no_space_info.html') + + def recipe_view(request, pk, share=None): with scopes_disabled(): recipe = get_object_or_404(Recipe, pk=pk) @@ -331,11 +335,8 @@ def system(request): def setup(request): - if (User.objects.count() > 0 - or 'django.contrib.auth.backends.RemoteUserBackend' in settings.AUTHENTICATION_BACKENDS): # noqa: E501 - messages.add_message(request, messages.ERROR, - _('The setup page can only be used to create the first user! If you have forgotten your superuser credentials please consult the django documentation on how to reset passwords.') # noqa: E501 - ) + if User.objects.count() > 0 or 'django.contrib.auth.backends.RemoteUserBackend' in settings.AUTHENTICATION_BACKENDS: + messages.add_message(request, messages.ERROR, _('The setup page can only be used to create the first user! If you have forgotten your superuser credentials please consult the django documentation on how to reset passwords.')) return HttpResponseRedirect(reverse('account_login')) if request.method == 'POST': @@ -344,20 +345,19 @@ def setup(request): if form.cleaned_data['password'] != form.cleaned_data['password_confirm']: # noqa: E501 form.add_error('password', _('Passwords dont match!')) else: - user = User( - username=form.cleaned_data['name'], - is_superuser=True, - is_staff=True - ) + user = User(username=form.cleaned_data['name'], is_superuser=True, is_staff=True) try: validate_password(form.cleaned_data['password'], user=user) user.set_password(form.cleaned_data['password']) user.save() - messages.add_message( - request, - messages.SUCCESS, - _('User has been created, please login!') - ) + user.userpreference.space = Space.objects.first() + user.userpreference.save() + + with scopes_disabled(): + for x in Space.objects.all(): + x.created_by = user + x.save() + messages.add_message(request, messages.SUCCESS, _('User has been created, please login!')) return HttpResponseRedirect(reverse('account_login')) except ValidationError as e: for m in e: @@ -369,60 +369,52 @@ def setup(request): def signup(request, token): - try: - token = UUID(token, version=4) - except ValueError: - messages.add_message(request, messages.ERROR, _('Malformed Invite Link supplied!')) - return HttpResponseRedirect(reverse('index')) + with scopes_disabled(): + try: + token = UUID(token, version=4) + except ValueError: + messages.add_message(request, messages.ERROR, _('Malformed Invite Link supplied!')) + return HttpResponseRedirect(reverse('index')) + + if link := InviteLink.objects.filter(valid_until__gte=datetime.today(), used_by=None, uuid=token).first(): + if request.method == 'POST': + updated_request = request.POST.copy() + if link.username != '': + updated_request.update({'name': link.username}) + + form = UserCreateForm(updated_request) + + if form.is_valid(): + if form.cleaned_data['password'] != form.cleaned_data['password_confirm']: # noqa: E501 + form.add_error('password', _('Passwords dont match!')) + else: + user = User(username=form.cleaned_data['name'], ) + try: + validate_password(form.cleaned_data['password'], user=user) + user.set_password(form.cleaned_data['password']) + user.save() + messages.add_message(request, messages.SUCCESS, _('User has been created, please login!')) + + link.used_by = user + link.save() + user.groups.add(link.group) + + user.userpreference.space = link.space + user.userpreference.save() + return HttpResponseRedirect(reverse('account_login')) + except ValidationError as e: + for m in e: + form.add_error('password', m) + else: + form = UserCreateForm() - if link := InviteLink.objects.filter(valid_until__gte=datetime.today(), used_by=None, uuid=token).first(): - if request.method == 'POST': - updated_request = request.POST.copy() if link.username != '': - updated_request.update({'name': link.username}) + form.fields['name'].initial = link.username + form.fields['name'].disabled = True + return render(request, 'account/signup.html', {'form': form, 'link': link}) - form = UserCreateForm(updated_request) - - if form.is_valid(): - if form.cleaned_data['password'] != form.cleaned_data['password_confirm']: # noqa: E501 - form.add_error('password', _('Passwords dont match!')) - else: - user = User( - username=form.cleaned_data['name'], - ) - try: - validate_password( - form.cleaned_data['password'], user=user - ) - user.set_password(form.cleaned_data['password']) - user.save() - messages.add_message( - request, - messages.SUCCESS, - _('User has been created, please login!') - ) - - link.used_by = user - link.save() - user.groups.add(link.group) - return HttpResponseRedirect(reverse('account_login')) - except ValidationError as e: - for m in e: - form.add_error('password', m) - else: - form = UserCreateForm() - - if link.username != '': - form.fields['name'].initial = link.username - form.fields['name'].disabled = True - return render( - request, 'account/signup.html', {'form': form, 'link': link} - ) - - messages.add_message( - request, messages.ERROR, _('Invite Link not valid or already used!') - ) - return HttpResponseRedirect(reverse('index')) + messages.add_message(request, messages.ERROR, _('Invite Link not valid or already used!')) + return HttpResponseRedirect(reverse('index')) def markdown_info(request): From 24e43e3e2edf8523b7f1d77aca3c550a32120d06 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sun, 21 Feb 2021 15:34:35 +0100 Subject: [PATCH 21/96] updated migrations + setup process update --- cookbook/admin.py | 2 +- cookbook/helper/scope_middleware.py | 16 ++--- .../migrations/0010_auto_20200130_1059.py | 20 ++++--- .../migrations/0021_auto_20200216_2309.py | 20 ++++--- .../migrations/0034_auto_20200426_1614.py | 14 +++-- .../migrations/0036_auto_20200427_1800.py | 14 +++-- .../migrations/0047_auto_20200602_1133.py | 58 ++++++++++--------- .../migrations/0050_auto_20200611_1509.py | 24 ++++---- .../migrations/0056_auto_20200625_2157.py | 7 ++- .../migrations/0059_auto_20200625_2137.py | 14 +++-- .../migrations/0062_auto_20200625_2219.py | 24 ++++---- .../migrations/0068_auto_20200629_2127.py | 34 ++++++----- cookbook/views/views.py | 58 +++++++++---------- 13 files changed, 164 insertions(+), 141 deletions(-) diff --git a/cookbook/admin.py b/cookbook/admin.py index 8893a7a0..b96fa2e4 100644 --- a/cookbook/admin.py +++ b/cookbook/admin.py @@ -22,7 +22,7 @@ admin.site.unregister(Group) class SpaceAdmin(admin.ModelAdmin): - list_display = ('name', 'message') + list_display = ('name', 'created_by', 'message') admin.site.register(Space, SpaceAdmin) diff --git a/cookbook/helper/scope_middleware.py b/cookbook/helper/scope_middleware.py index 9726d526..6dacc5b9 100644 --- a/cookbook/helper/scope_middleware.py +++ b/cookbook/helper/scope_middleware.py @@ -2,6 +2,8 @@ from django.shortcuts import redirect from django.urls import reverse from django_scopes import scope, scopes_disabled +from cookbook.views import views + class ScopeMiddleware: def __init__(self, get_response): @@ -10,17 +12,17 @@ class ScopeMiddleware: def __call__(self, request): if request.user.is_authenticated: - if request.user.groups.count() == 0: - return redirect('view_no_group') - - with scopes_disabled(): - if request.user.userpreference.space is None and not reverse('view_no_space') in request.path and not reverse('account_logout') in request.path: - return redirect(reverse('view_no_space')) - if request.path.startswith('/admin/'): with scopes_disabled(): return self.get_response(request) + with scopes_disabled(): + if request.user.userpreference.space is None and not reverse('account_logout') in request.path: + return views.no_space(request) + + if request.user.groups.count() == 0 and not reverse('account_logout') in request.path: + return views.no_groups(request) + request.space = request.user.userpreference.space # with scopes_disabled(): with scope(space=request.space): diff --git a/cookbook/migrations/0010_auto_20200130_1059.py b/cookbook/migrations/0010_auto_20200130_1059.py index 3ef2f066..ffd49acc 100644 --- a/cookbook/migrations/0010_auto_20200130_1059.py +++ b/cookbook/migrations/0010_auto_20200130_1059.py @@ -1,20 +1,22 @@ # Generated by Django 3.0.2 on 2020-01-30 09:59 from django.db import migrations +from django_scopes import scopes_disabled def migrate_ingredient_units(apps, schema_editor): - Unit = apps.get_model('cookbook', 'Unit') - RecipeIngredients = apps.get_model('cookbook', 'RecipeIngredients') + with scopes_disabled(): + Unit = apps.get_model('cookbook', 'Unit') + RecipeIngredients = apps.get_model('cookbook', 'RecipeIngredients') - for u in RecipeIngredients.objects.values('unit').distinct(): - unit = Unit() - unit.name = u['unit'] - unit.save() + for u in RecipeIngredients.objects.values('unit').distinct(): + unit = Unit() + unit.name = u['unit'] + unit.save() - for i in RecipeIngredients.objects.all(): - i.unit_key = Unit.objects.get(name=i.unit) - i.save() + for i in RecipeIngredients.objects.all(): + i.unit_key = Unit.objects.get(name=i.unit) + i.save() class Migration(migrations.Migration): diff --git a/cookbook/migrations/0021_auto_20200216_2309.py b/cookbook/migrations/0021_auto_20200216_2309.py index 1d111549..617dd9ef 100644 --- a/cookbook/migrations/0021_auto_20200216_2309.py +++ b/cookbook/migrations/0021_auto_20200216_2309.py @@ -1,19 +1,21 @@ # Generated by Django 3.0.2 on 2020-02-16 22:09 from django.db import migrations +from django_scopes import scopes_disabled def migrate_ingredients(apps, schema_editor): - Ingredient = apps.get_model('cookbook', 'Ingredient') - RecipeIngredient = apps.get_model('cookbook', 'RecipeIngredient') + with scopes_disabled(): + Ingredient = apps.get_model('cookbook', 'Ingredient') + RecipeIngredient = apps.get_model('cookbook', 'RecipeIngredient') - for u in RecipeIngredient.objects.values('name').distinct(): - ingredient = Ingredient() - ingredient.name = u['name'] - ingredient.save() + for u in RecipeIngredient.objects.values('name').distinct(): + ingredient = Ingredient() + ingredient.name = u['name'] + ingredient.save() - for i in RecipeIngredient.objects.all(): - i.ingredient = Ingredient.objects.get(name=i.name) - i.save() + for i in RecipeIngredient.objects.all(): + i.ingredient = Ingredient.objects.get(name=i.name) + i.save() class Migration(migrations.Migration): diff --git a/cookbook/migrations/0034_auto_20200426_1614.py b/cookbook/migrations/0034_auto_20200426_1614.py index ee3797aa..a7844e6d 100644 --- a/cookbook/migrations/0034_auto_20200426_1614.py +++ b/cookbook/migrations/0034_auto_20200426_1614.py @@ -1,15 +1,17 @@ # Generated by Django 3.0.5 on 2020-04-26 14:14 from django.db import migrations +from django_scopes import scopes_disabled def apply_migration(apps, schema_editor): - Group = apps.get_model('auth', 'Group') - Group.objects.bulk_create([ - Group(name=u'guest'), - Group(name=u'user'), - Group(name=u'admin'), - ]) + with scopes_disabled(): + Group = apps.get_model('auth', 'Group') + Group.objects.bulk_create([ + Group(name=u'guest'), + Group(name=u'user'), + Group(name=u'admin'), + ]) class Migration(migrations.Migration): diff --git a/cookbook/migrations/0036_auto_20200427_1800.py b/cookbook/migrations/0036_auto_20200427_1800.py index 25ee2f9d..f47cb832 100644 --- a/cookbook/migrations/0036_auto_20200427_1800.py +++ b/cookbook/migrations/0036_auto_20200427_1800.py @@ -1,15 +1,17 @@ # Generated by Django 3.0.5 on 2020-04-27 16:00 from django.db import migrations +from django_scopes import scopes_disabled def apply_migration(apps, schema_editor): - Group = apps.get_model('auth', 'Group') - User = apps.get_model('auth', 'User') - for u in User.objects.all(): - if u.groups.count() < 1: - u.groups.add(Group.objects.get(name='admin')) - u.save() + with scopes_disabled(): + Group = apps.get_model('auth', 'Group') + User = apps.get_model('auth', 'User') + for u in User.objects.all(): + if u.groups.count() < 1: + u.groups.add(Group.objects.get(name='admin')) + u.save() class Migration(migrations.Migration): diff --git a/cookbook/migrations/0047_auto_20200602_1133.py b/cookbook/migrations/0047_auto_20200602_1133.py index cc500a26..d9287457 100644 --- a/cookbook/migrations/0047_auto_20200602_1133.py +++ b/cookbook/migrations/0047_auto_20200602_1133.py @@ -2,43 +2,45 @@ from django.db import migrations from django.utils.translation import gettext as _ +from django_scopes import scopes_disabled def migrate_meal_types(apps, schema_editor): - MealPlan = apps.get_model('cookbook', 'MealPlan') - MealType = apps.get_model('cookbook', 'MealType') + with scopes_disabled(): + MealPlan = apps.get_model('cookbook', 'MealPlan') + MealType = apps.get_model('cookbook', 'MealType') - breakfast = MealType.objects.create( - name=_('Breakfast'), - order=0, - ) + breakfast = MealType.objects.create( + name=_('Breakfast'), + order=0, + ) - lunch = MealType.objects.create( - name=_('Lunch'), - order=0, - ) + lunch = MealType.objects.create( + name=_('Lunch'), + order=0, + ) - dinner = MealType.objects.create( - name=_('Dinner'), - order=0, - ) + dinner = MealType.objects.create( + name=_('Dinner'), + order=0, + ) - other = MealType.objects.create( - name=_('Other'), - order=0, - ) + other = MealType.objects.create( + name=_('Other'), + order=0, + ) - for m in MealPlan.objects.all(): - if m.meal == 'BREAKFAST': - m.meal_type = breakfast - if m.meal == 'LUNCH': - m.meal_type = lunch - if m.meal == 'DINNER': - m.meal_type = dinner - if m.meal == 'OTHER': - m.meal_type = other + for m in MealPlan.objects.all(): + if m.meal == 'BREAKFAST': + m.meal_type = breakfast + if m.meal == 'LUNCH': + m.meal_type = lunch + if m.meal == 'DINNER': + m.meal_type = dinner + if m.meal == 'OTHER': + m.meal_type = other - m.save() + m.save() class Migration(migrations.Migration): diff --git a/cookbook/migrations/0050_auto_20200611_1509.py b/cookbook/migrations/0050_auto_20200611_1509.py index 7c841368..e5e6404c 100644 --- a/cookbook/migrations/0050_auto_20200611_1509.py +++ b/cookbook/migrations/0050_auto_20200611_1509.py @@ -2,22 +2,24 @@ from django.db import migrations from django.db.models import Q +from django_scopes import scopes_disabled def migrate_meal_types(apps, schema_editor): - MealPlan = apps.get_model('cookbook', 'MealPlan') - MealType = apps.get_model('cookbook', 'MealType') - User = apps.get_model('auth', 'User') + with scopes_disabled(): + MealPlan = apps.get_model('cookbook', 'MealPlan') + MealType = apps.get_model('cookbook', 'MealType') + User = apps.get_model('auth', 'User') - for u in User.objects.all(): - for t in MealType.objects.filter(created_by=None).all(): - user_type = MealType.objects.create( - name=t.name, - created_by=u, - ) - MealPlan.objects.filter(Q(created_by=u) and Q(meal_type=t)).update(meal_type=user_type) + for u in User.objects.all(): + for t in MealType.objects.filter(created_by=None).all(): + user_type = MealType.objects.create( + name=t.name, + created_by=u, + ) + MealPlan.objects.filter(Q(created_by=u) and Q(meal_type=t)).update(meal_type=user_type) - MealType.objects.filter(created_by=None).delete() + MealType.objects.filter(created_by=None).delete() class Migration(migrations.Migration): diff --git a/cookbook/migrations/0056_auto_20200625_2157.py b/cookbook/migrations/0056_auto_20200625_2157.py index 65a6e281..8a0a3bfd 100644 --- a/cookbook/migrations/0056_auto_20200625_2157.py +++ b/cookbook/migrations/0056_auto_20200625_2157.py @@ -3,11 +3,14 @@ from django.db import migrations, models import uuid +from django_scopes import scopes_disabled + def invalidate_shares(apps, schema_editor): - ShareLink = apps.get_model('cookbook', 'ShareLink') + with scopes_disabled(): + ShareLink = apps.get_model('cookbook', 'ShareLink') - ShareLink.objects.all().delete() + ShareLink.objects.all().delete() class Migration(migrations.Migration): diff --git a/cookbook/migrations/0059_auto_20200625_2137.py b/cookbook/migrations/0059_auto_20200625_2137.py index 58781b3f..09cb1d42 100644 --- a/cookbook/migrations/0059_auto_20200625_2137.py +++ b/cookbook/migrations/0059_auto_20200625_2137.py @@ -1,16 +1,18 @@ # Generated by Django 3.0.7 on 2020-06-25 19:37 from django.db import migrations +from django_scopes import scopes_disabled def migrate_ingredients(apps, schema_editor): - Recipe = apps.get_model('cookbook', 'Recipe') - Ingredient = apps.get_model('cookbook', 'Ingredient') + with scopes_disabled(): + Recipe = apps.get_model('cookbook', 'Recipe') + Ingredient = apps.get_model('cookbook', 'Ingredient') - for r in Recipe.objects.all(): - for i in Ingredient.objects.filter(recipe=r).all(): - r.ingredients.add(i) - r.save() + for r in Recipe.objects.all(): + for i in Ingredient.objects.filter(recipe=r).all(): + r.ingredients.add(i) + r.save() class Migration(migrations.Migration): diff --git a/cookbook/migrations/0062_auto_20200625_2219.py b/cookbook/migrations/0062_auto_20200625_2219.py index c852a020..7dd1efd7 100644 --- a/cookbook/migrations/0062_auto_20200625_2219.py +++ b/cookbook/migrations/0062_auto_20200625_2219.py @@ -1,21 +1,23 @@ # Generated by Django 3.0.7 on 2020-06-25 20:19 from django.db import migrations, models +from django_scopes import scopes_disabled def create_default_step(apps, schema_editor): - Recipe = apps.get_model('cookbook', 'Recipe') - Step = apps.get_model('cookbook', 'Step') + with scopes_disabled(): + Recipe = apps.get_model('cookbook', 'Recipe') + Step = apps.get_model('cookbook', 'Step') - for r in Recipe.objects.filter(internal=True).all(): - s = Step.objects.create( - instruction=r.instructions - ) - for i in r.ingredients.all(): - s.ingredients.add(i) - s.save() - r.steps.add(s) - r.save() + for r in Recipe.objects.filter(internal=True).all(): + s = Step.objects.create( + instruction=r.instructions + ) + for i in r.ingredients.all(): + s.ingredients.add(i) + s.save() + r.steps.add(s) + r.save() class Migration(migrations.Migration): diff --git a/cookbook/migrations/0068_auto_20200629_2127.py b/cookbook/migrations/0068_auto_20200629_2127.py index daea00bd..7f92dff2 100644 --- a/cookbook/migrations/0068_auto_20200629_2127.py +++ b/cookbook/migrations/0068_auto_20200629_2127.py @@ -2,27 +2,29 @@ from django.db import migrations, models import django.db.models.deletion +from django_scopes import scopes_disabled def convert_old_specials(apps, schema_editor): - Ingredient = apps.get_model('cookbook', 'Ingredient') - Food = apps.get_model('cookbook', 'Food') - Unit = apps.get_model('cookbook', 'Unit') + with scopes_disabled(): + Ingredient = apps.get_model('cookbook', 'Ingredient') + Food = apps.get_model('cookbook', 'Food') + Unit = apps.get_model('cookbook', 'Unit') - for i in Ingredient.objects.all(): - if i.amount == 0: - i.no_amount = True - if i.unit.name == 'Special:Header': - i.header = True - i.unit = None - i.food = None - i.save() + for i in Ingredient.objects.all(): + if i.amount == 0: + i.no_amount = True + if i.unit.name == 'Special:Header': + i.header = True + i.unit = None + i.food = None + i.save() - try: - Unit.objects.filter(name='Special:Header').delete() - Food.objects.filter(name='Header').delete() - except Exception: - pass + try: + Unit.objects.filter(name='Special:Header').delete() + Food.objects.filter(name='Header').delete() + except Exception: + pass class Migration(migrations.Migration): diff --git a/cookbook/views/views.py b/cookbook/views/views.py index f781a766..74886145 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -7,6 +7,7 @@ from django.conf import settings from django.contrib import messages from django.contrib.auth import update_session_auth_hash from django.contrib.auth.forms import PasswordChangeForm +from django.contrib.auth.models import Group from django.contrib.auth.password_validation import validate_password from django.core.exceptions import ValidationError from django.db import IntegrityError @@ -85,10 +86,6 @@ def search(request): def no_groups(request): - if not request.user.is_authenticated: - return HttpResponseRedirect(reverse('account_login') + '?next=' + request.GET['next']) - if request.user.is_authenticated and request.user.groups.count() > 0: - return HttpResponseRedirect(reverse('index')) return render(request, 'no_groups_info.html') @@ -335,37 +332,40 @@ def system(request): def setup(request): - if User.objects.count() > 0 or 'django.contrib.auth.backends.RemoteUserBackend' in settings.AUTHENTICATION_BACKENDS: - messages.add_message(request, messages.ERROR, _('The setup page can only be used to create the first user! If you have forgotten your superuser credentials please consult the django documentation on how to reset passwords.')) - return HttpResponseRedirect(reverse('account_login')) + with scopes_disabled(): + if User.objects.count() > 0 or 'django.contrib.auth.backends.RemoteUserBackend' in settings.AUTHENTICATION_BACKENDS: + messages.add_message(request, messages.ERROR, _('The setup page can only be used to create the first user! If you have forgotten your superuser credentials please consult the django documentation on how to reset passwords.')) + return HttpResponseRedirect(reverse('account_login')) - if request.method == 'POST': - form = UserCreateForm(request.POST) - if form.is_valid(): - if form.cleaned_data['password'] != form.cleaned_data['password_confirm']: # noqa: E501 - form.add_error('password', _('Passwords dont match!')) - else: - user = User(username=form.cleaned_data['name'], is_superuser=True, is_staff=True) - try: - validate_password(form.cleaned_data['password'], user=user) - user.set_password(form.cleaned_data['password']) - user.save() - user.userpreference.space = Space.objects.first() - user.userpreference.save() + if request.method == 'POST': + form = UserCreateForm(request.POST) + if form.is_valid(): + if form.cleaned_data['password'] != form.cleaned_data['password_confirm']: + form.add_error('password', _('Passwords dont match!')) + else: + user = User(username=form.cleaned_data['name'], is_superuser=True, is_staff=True) + try: + validate_password(form.cleaned_data['password'], user=user) + user.set_password(form.cleaned_data['password']) + user.save() + + user.groups.add(Group.objects.get(name='admin')) + + user.userpreference.space = Space.objects.first() + user.userpreference.save() - with scopes_disabled(): for x in Space.objects.all(): x.created_by = user x.save() - messages.add_message(request, messages.SUCCESS, _('User has been created, please login!')) - return HttpResponseRedirect(reverse('account_login')) - except ValidationError as e: - for m in e: - form.add_error('password', m) - else: - form = UserCreateForm() + messages.add_message(request, messages.SUCCESS, _('User has been created, please login!')) + return HttpResponseRedirect(reverse('account_login')) + except ValidationError as e: + for m in e: + form.add_error('password', m) + else: + form = UserCreateForm() - return render(request, 'setup.html', {'form': form}) + return render(request, 'setup.html', {'form': form}) def signup(request, token): From 46fb02376e00750c29222952e5cdeaa5dad89ba1 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sun, 21 Feb 2021 16:37:04 +0100 Subject: [PATCH 22/96] recipe share basics --- cookbook/helper/permission_helper.py | 2 +- cookbook/helper/scope_middleware.py | 4 +- cookbook/templates/no_groups_info.html | 7 +- cookbook/templates/no_perm_info.html | 20 +++++ cookbook/templates/no_space_info.html | 2 +- cookbook/urls.py | 1 + cookbook/views/api.py | 7 +- cookbook/views/views.py | 106 ++++++++++--------------- 8 files changed, 80 insertions(+), 69 deletions(-) create mode 100644 cookbook/templates/no_perm_info.html diff --git a/cookbook/helper/permission_helper.py b/cookbook/helper/permission_helper.py index ebd7d082..e170063f 100644 --- a/cookbook/helper/permission_helper.py +++ b/cookbook/helper/permission_helper.py @@ -108,7 +108,7 @@ def group_required(*groups_required): def in_groups(u): return has_group_permission(u, groups_required) - return user_passes_test(in_groups, login_url='view_no_group') + return user_passes_test(in_groups, login_url='view_no_perm') class GroupRequiredMixin(object): diff --git a/cookbook/helper/scope_middleware.py b/cookbook/helper/scope_middleware.py index 6dacc5b9..6b5191df 100644 --- a/cookbook/helper/scope_middleware.py +++ b/cookbook/helper/scope_middleware.py @@ -28,4 +28,6 @@ class ScopeMiddleware: with scope(space=request.space): return self.get_response(request) else: - return self.get_response(request) + with scopes_disabled(): + request.space = None + return self.get_response(request) diff --git a/cookbook/templates/no_groups_info.html b/cookbook/templates/no_groups_info.html index eac51be1..1059e11a 100644 --- a/cookbook/templates/no_groups_info.html +++ b/cookbook/templates/no_groups_info.html @@ -12,7 +12,12 @@

{% trans 'No Permissions' %}


- {% trans 'You do not have any groups and therefor cannot use this application. Please contact your administrator.' %}
+ + + {% trans 'You do not have any groups and therefor cannot use this application.' %} + {% trans 'Please contact your administrator.' %} + +
diff --git a/cookbook/templates/no_perm_info.html b/cookbook/templates/no_perm_info.html new file mode 100644 index 00000000..a2cb50cc --- /dev/null +++ b/cookbook/templates/no_perm_info.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} +{% load static %} +{% load i18n %} + +{% block title %}{% trans "No Permission" %}{% endblock %} + + +{% block content %} + +
+ +

{% trans 'No Permission' %}

+
+ + {% trans 'You do not have the required permissions to view this page or perform this action.' %} {% trans 'Please contact your administrator.' %}
+ +
+ +{% endblock %} + diff --git a/cookbook/templates/no_space_info.html b/cookbook/templates/no_space_info.html index f8ad26e8..e8525f5c 100644 --- a/cookbook/templates/no_space_info.html +++ b/cookbook/templates/no_space_info.html @@ -12,7 +12,7 @@

{% trans 'No Space' %}


- {% trans 'You are not a member of any space. Please contact your administrator.' %}
+ {% trans 'You are not a member of any space.' %} {% trans 'Please contact your administrator.' %}
diff --git a/cookbook/urls.py b/cookbook/urls.py index c446a1b6..4f055703 100644 --- a/cookbook/urls.py +++ b/cookbook/urls.py @@ -41,6 +41,7 @@ urlpatterns = [ path('setup/', views.setup, name='view_setup'), path('no-group', views.no_groups, name='view_no_group'), path('no-space', views.no_space, name='view_no_space'), + path('no-perm', views.no_perm, name='view_no_perm'), path('signup/', views.signup, name='view_signup'), path('system/', views.system, name='view_system'), path('search/', views.search, name='view_search'), diff --git a/cookbook/views/api.py b/cookbook/views/api.py index a4add1cc..59c8b261 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -289,13 +289,14 @@ class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin): permission_classes = [CustomIsShare | CustomIsGuest] def get_queryset(self): - queryset = self.queryset.filter(space=self.request.user.userpreference.space) + if self.request.space: + self.queryset = self.queryset.filter(space=self.request.space) internal = self.request.query_params.get('internal', None) if internal: - queryset = queryset.filter(internal=True) + self.queryset = self.queryset.filter(internal=True) - return queryset + return self.queryset # TODO write extensive tests for permissions diff --git a/cookbook/views/views.py b/cookbook/views/views.py index 74886145..d2f2faef 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -50,15 +50,12 @@ def index(request): return HttpResponseRedirect(page_map.get(request.user.userpreference.default_page)) except UserPreference.DoesNotExist: - return HttpResponseRedirect(reverse('view_no_group') + '?next=' + request.path) + return HttpResponseRedirect(reverse('view_search')) def search(request): if has_group_permission(request.user, ('guest',)): - f = RecipeFilter( - request.GET, - queryset=Recipe.objects.filter(space=request.user.userpreference.space).all().order_by('name') - ) + f = RecipeFilter(request.GET, queryset=Recipe.objects.filter(space=request.user.userpreference.space).all().order_by('name')) if request.user.userpreference.search_style == UserPreference.LARGE: table = RecipeTable(f.qs) @@ -82,7 +79,10 @@ def search(request): return render(request, 'index.html', {'recipes': table, 'filter': f, 'last_viewed': last_viewed}) else: - return HttpResponseRedirect(reverse('view_no_group') + '?next=' + request.path) + if request.user.is_authenticated: + return HttpResponseRedirect(reverse('view_no_group')) + else: + return HttpResponseRedirect(reverse('account_login') + '?next=' + request.path) def no_groups(request): @@ -93,76 +93,58 @@ def no_space(request): return render(request, 'no_space_info.html') +def no_perm(request): + return render(request, 'no_perm_info.html') + + def recipe_view(request, pk, share=None): with scopes_disabled(): recipe = get_object_or_404(Recipe, pk=pk) - if not (has_group_permission(request.user, ('guest',)) and recipe.space == request.space) and not share_link_valid(recipe, share): - messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) - return HttpResponseRedirect(reverse('view_no_group') + '?next=' + request.path) + if not request.user.is_authenticated and not share_link_valid(recipe, share): + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) + return HttpResponseRedirect(reverse('account_login') + '?next=' + request.path) - comments = Comment.objects.filter(recipe__space=request.space, recipe=recipe) + if not (has_group_permission(request.user, ('guest',)) and recipe.space == request.space) and not share_link_valid(recipe, share): + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) + return HttpResponseRedirect(reverse('index')) - if request.method == "POST": - if not request.user.is_authenticated: - messages.add_message( - request, - messages.ERROR, - _('You do not have the required permissions to perform this action!') # noqa: E501 - ) - return HttpResponseRedirect( - reverse( - 'view_recipe', - kwargs={'pk': recipe.pk, 'share': share} - ) - ) + comments = Comment.objects.filter(recipe__space=request.space, recipe=recipe) - comment_form = CommentForm(request.POST, prefix='comment') - if comment_form.is_valid(): - comment = Comment() - comment.recipe = recipe - comment.text = comment_form.cleaned_data['text'] - comment.created_by = request.user + if request.method == "POST": + if not request.user.is_authenticated: + messages.add_message(request, messages.ERROR, _('You do not have the required permissions to perform this action!')) + return HttpResponseRedirect(reverse('view_recipe', kwargs={'pk': recipe.pk, 'share': share})) - comment.save() + comment_form = CommentForm(request.POST, prefix='comment') + if comment_form.is_valid(): + comment = Comment() + comment.recipe = recipe + comment.text = comment_form.cleaned_data['text'] + comment.created_by = request.user + comment.save() - messages.add_message( - request, messages.SUCCESS, _('Comment saved!') - ) + messages.add_message(request, messages.SUCCESS, _('Comment saved!')) - bookmark_form = RecipeBookEntryForm(request.POST, prefix='bookmark', space=request.space) - if bookmark_form.is_valid(): - bookmark = RecipeBookEntry() - bookmark.recipe = recipe - bookmark.book = bookmark_form.cleaned_data['book'] + comment_form = CommentForm() - try: - bookmark.save() - except IntegrityError as e: - if 'UNIQUE constraint' in str(e.args): - messages.add_message(request, messages.ERROR, _('This recipe is already linked to the book!')) - else: - messages.add_message(request, messages.SUCCESS, _('Bookmark saved!')) + user_servings = None + if request.user.is_authenticated: + user_servings = CookLog.objects.filter( + recipe=recipe, + created_by=request.user, + servings__gt=0, + space=request.space, + ).all().aggregate(Avg('servings'))['servings__avg'] - comment_form = CommentForm() + if not user_servings: + user_servings = 0 - user_servings = None - if request.user.is_authenticated: - user_servings = CookLog.objects.filter( - recipe=recipe, - created_by=request.user, - servings__gt=0, - space=request.space, - ).all().aggregate(Avg('servings'))['servings__avg'] + if request.user.is_authenticated: + if not ViewLog.objects.filter(recipe=recipe, created_by=request.user, created_at__gt=(timezone.now() - timezone.timedelta(minutes=5)), space=request.space).exists(): + ViewLog.objects.create(recipe=recipe, created_by=request.user, space=request.space) - if not user_servings: - user_servings = 0 - - if request.user.is_authenticated: - if not ViewLog.objects.filter(recipe=recipe, created_by=request.user, created_at__gt=(timezone.now() - timezone.timedelta(minutes=5)), space=request.space).exists(): - ViewLog.objects.create(recipe=recipe, created_by=request.user, space=request.space) - - return render(request, 'recipe_view.html', {'recipe': recipe, 'comments': comments, 'comment_form': comment_form, 'share': share, 'user_servings': user_servings}) + return render(request, 'recipe_view.html', {'recipe': recipe, 'comments': comments, 'comment_form': comment_form, 'share': share, 'user_servings': user_servings}) @group_required('user') From 40387428e7475cb0d14e9afac771498d656d9c96 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Sun, 21 Feb 2021 16:49:34 +0100 Subject: [PATCH 23/96] recipe filter --- cookbook/filters.py | 25 +++++++++++++------------ cookbook/views/lists.py | 4 ++-- cookbook/views/views.py | 2 +- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/cookbook/filters.py b/cookbook/filters.py index 2d75bde3..b35cd36f 100644 --- a/cookbook/filters.py +++ b/cookbook/filters.py @@ -12,17 +12,23 @@ with scopes_disabled(): class RecipeFilter(django_filters.FilterSet): name = django_filters.CharFilter(method='filter_name') keywords = django_filters.ModelMultipleChoiceFilter( - queryset=Keyword.objects.all(), + queryset=Keyword.objects.none(), widget=MultiSelectWidget, method='filter_keywords' ) foods = django_filters.ModelMultipleChoiceFilter( - queryset=Food.objects.all(), + queryset=Food.objects.none(), widget=MultiSelectWidget, method='filter_foods', label=_('Ingredients') ) + def __init__(self, data=None, *args, **kwargs): + space = kwargs.pop('space') + super().__init__(data, *args, **kwargs) + self.filters['foods'].queryset = Food.objects.filter(space=space).all() + self.filters['keywords'].queryset = Keyword.objects.filter(space=space).all() + @staticmethod def filter_keywords(queryset, name, value): if not name == 'keywords': @@ -36,20 +42,15 @@ with scopes_disabled(): if not name == 'foods': return queryset for x in value: - queryset = queryset.filter( - steps__ingredients__food__name=x - ).distinct() + queryset = queryset.filter(steps__ingredients__food__name=x).distinct() return queryset @staticmethod def filter_name(queryset, name, value): if not name == 'name': return queryset - if settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql_psycopg2': # noqa: E501 - queryset = queryset \ - .annotate(similarity=TrigramSimilarity('name', value), ) \ - .filter(Q(similarity__gt=0.1) | Q(name__unaccent__icontains=value)) \ - .order_by('-similarity') + if settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql_psycopg2': + queryset = queryset.annotate(similarity=TrigramSimilarity('name', value), ).filter(Q(similarity__gt=0.1) | Q(name__unaccent__icontains=value)).order_by('-similarity') else: queryset = queryset.filter(name__icontains=value) return queryset @@ -59,7 +60,7 @@ with scopes_disabled(): fields = ['name', 'keywords', 'foods', 'internal'] - class IngredientFilter(django_filters.FilterSet): + class FoodFilter(django_filters.FilterSet): name = django_filters.CharFilter(lookup_expr='icontains') class Meta: @@ -73,7 +74,7 @@ with scopes_disabled(): if data is not None: data = data.copy() data.setdefault("finished", False) - super(ShoppingListFilter, self).__init__(data, *args, **kwargs) + super().__init__(data, *args, **kwargs) class Meta: model = ShoppingList diff --git a/cookbook/views/lists.py b/cookbook/views/lists.py index 7cfcb229..433aa980 100644 --- a/cookbook/views/lists.py +++ b/cookbook/views/lists.py @@ -6,7 +6,7 @@ from django.shortcuts import render from django.utils.translation import gettext as _ from django_tables2 import RequestConfig -from cookbook.filters import IngredientFilter, ShoppingListFilter +from cookbook.filters import FoodFilter, ShoppingListFilter from cookbook.helper.permission_helper import group_required from cookbook.models import (Food, InviteLink, Keyword, RecipeImport, ShoppingList, Storage, SyncLog) @@ -56,7 +56,7 @@ def recipe_import(request): @group_required('user') def food(request): - f = IngredientFilter(request.GET, queryset=Food.objects.filter(space=request.space).all().order_by('pk')) + f = FoodFilter(request.GET, queryset=Food.objects.filter(space=request.space).all().order_by('pk')) table = IngredientTable(f.qs) RequestConfig(request, paginate={'per_page': 25}).configure(table) diff --git a/cookbook/views/views.py b/cookbook/views/views.py index d2f2faef..0cb152dd 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -55,7 +55,7 @@ def index(request): def search(request): if has_group_permission(request.user, ('guest',)): - f = RecipeFilter(request.GET, queryset=Recipe.objects.filter(space=request.user.userpreference.space).all().order_by('name')) + f = RecipeFilter(request.GET, queryset=Recipe.objects.filter(space=request.user.userpreference.space).all().order_by('name'), space=request.space) if request.user.userpreference.search_style == UserPreference.LARGE: table = RecipeTable(f.qs) From 1c43be3899aefa0f55d834a5093c057e7e722f81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Feb 2021 07:00:29 +0000 Subject: [PATCH 24/96] Bump django-crispy-forms from 1.11.0 to 1.11.1 Bumps [django-crispy-forms](https://github.com/django-crispy-forms/django-crispy-forms) from 1.11.0 to 1.11.1. - [Release notes](https://github.com/django-crispy-forms/django-crispy-forms/releases) - [Changelog](https://github.com/django-crispy-forms/django-crispy-forms/blob/master/CHANGELOG.md) - [Commits](https://github.com/django-crispy-forms/django-crispy-forms/compare/1.11.0...1.11.1) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 61dce5f9..69658f45 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ Django==3.1.6 django-annoying==0.10.6 django-autocomplete-light==3.8.1 django-cleanup==5.1.0 -django-crispy-forms==1.11.0 +django-crispy-forms==1.11.1 django-emoji-picker==0.0.6 django-filter==2.4.0 django-tables2==2.3.4 From 689918c1ac57d141b249ec34ff93b8f5e506ef87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Feb 2021 07:00:34 +0000 Subject: [PATCH 25/96] Bump django from 3.1.6 to 3.1.7 Bumps [django](https://github.com/django/django) from 3.1.6 to 3.1.7. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/3.1.6...3.1.7) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 61dce5f9..827a3795 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ bleach==3.3.0 bleach-whitelist==0.0.11 -Django==3.1.6 +Django==3.1.7 django-annoying==0.10.6 django-autocomplete-light==3.8.1 django-cleanup==5.1.0 From cc882082d2d086d87cd9a3417b56cd765d1c780f Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Mon, 22 Feb 2021 15:41:54 +0000 Subject: [PATCH 26/96] Apply translations in de translation completed for the source file '/cookbook/locale/en/LC_MESSAGES/django.po' on the 'de' language. --- cookbook/locale/de/LC_MESSAGES/django.po | 796 ++++++++--------------- 1 file changed, 262 insertions(+), 534 deletions(-) diff --git a/cookbook/locale/de/LC_MESSAGES/django.po b/cookbook/locale/de/LC_MESSAGES/django.po index 9d8e5884..bdb830d5 100644 --- a/cookbook/locale/de/LC_MESSAGES/django.po +++ b/cookbook/locale/de/LC_MESSAGES/django.po @@ -2,11 +2,14 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Benjamin Danowski , 2020 # vabene1111 , 2020 -# +# Aaron Dötsch, 2020 +# Tobias Lindenberg , 2021 +# Maximilian J, 2021 +# #, fuzzy msgid "" msgstr "" @@ -14,13 +17,12 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-09 18:01+0100\n" "PO-Revision-Date: 2020-06-02 19:28+0000\n" -"Last-Translator: vabene1111 , 2020\n" -"Language-Team: German (https://www.transifex.com/django-recipes/teams/110507/" -"de/)\n" -"Language: de\n" +"Last-Translator: Maximilian J, 2021\n" +"Language-Team: German (https://www.transifex.com/django-recipes/teams/110507/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: .\cookbook\filters.py:22 .\cookbook\templates\base.html:87 @@ -46,21 +48,25 @@ msgstr "Standardeinheit für neue Zutaten." msgid "" "Enables support for fractions in ingredient amounts (e.g. convert decimals " "to fractions automatically)" -msgstr "Unterstützung für Brüche aktivieren in Zutaten aktivieren." +msgstr "" +"Unterstützung für Brüche in Zutaten aktivieren. Dadurch werden Dezimalzahlen" +" mit Brüchen ersetzt, z.B. 0.5 mit ½." #: .\cookbook\forms.py:47 msgid "" "Users with whom newly created meal plan/shopping list entries should be " "shared by default." msgstr "" +"Nutzer, mit denen neue Pläne und Einkaufslisten standardmäßig geteilt werden" +" sollen." #: .\cookbook\forms.py:48 msgid "Show recently viewed recipes on search page." -msgstr "Zeige zuletzt angeschaute Rezepte über den Suchergebnissen." +msgstr "Zuletzt angeschaute Rezepte bei der Suche anzeigen." #: .\cookbook\forms.py:49 msgid "Number of decimals to round ingredients." -msgstr "Anzahl Dezimalstellen, auf die gerundet werden soll." +msgstr "Anzahl an Dezimalstellen, auf die gerundet werden soll." #: .\cookbook\forms.py:50 msgid "If you want to be able to create and see comments underneath recipes." @@ -74,13 +80,13 @@ msgid "" "mobile data. If lower than instance limit it is reset when saving." msgstr "" "0 deaktiviert automatische Synchronisation. Wird eine Einkaufsliste " -"betrachtet, wird wird sie gemäß der Einstellung alle paar Sekunden " +"betrachtet, dann wird wird sie gemäß der Einstellung alle paar Sekunden " "aktualisiert. Dies ist nützlich, wenn mehrere Personen eine Liste beim " "Einkaufen verwenden, benötigt jedoch etwas Datenvolumen." #: .\cookbook\forms.py:55 msgid "Makes the navbar stick to the top of the page." -msgstr "" +msgstr "Navigationsleiste wird oben angeheftet." #: .\cookbook\forms.py:71 msgid "" @@ -116,25 +122,23 @@ msgstr "Pfad" #: .\cookbook\forms.py:97 msgid "Storage UID" -msgstr "Speicher ID" +msgstr "Speicher-ID" #: .\cookbook\forms.py:117 -#, fuzzy -#| msgid "Number of Days" msgid "Number of servings" -msgstr "Anzahl Tage" +msgstr "Anzahl der Portionen" #: .\cookbook\forms.py:128 msgid "" "Include - [ ] in list for easier usage in markdown based " "documents." msgstr "" -"Füge - [ ] vor den Zutaten ein, um sie besser in einem Markdown-" -"Dokument zu verwenden." +"Füge - [ ] vor den Zutaten ein, um sie besser in einem " +"Markdown-Dokument zu verwenden." #: .\cookbook\forms.py:143 msgid "Default" -msgstr "" +msgstr "Standard" #: .\cookbook\forms.py:162 msgid "New Unit" @@ -162,7 +166,7 @@ msgstr "Neue Zutat, die die alte ersetzt." #: .\cookbook\forms.py:185 msgid "Old Food" -msgstr "Alte Zutat." +msgstr "Alte Zutat" #: .\cookbook\forms.py:186 msgid "Food that should be replaced." @@ -182,11 +186,11 @@ msgstr "Für Nextcloud leer lassen, für Dropbox API-Token eingeben." #: .\cookbook\forms.py:244 msgid "" -"Leave empty for dropbox and enter only base url for nextcloud (/remote." -"php/webdav/ is added automatically)" +"Leave empty for dropbox and enter only base url for nextcloud " +"(/remote.php/webdav/ is added automatically)" msgstr "" -"Für Dropbox leer lassen. Für Nextcloud Server-URL angeben, (/remote." -"php/webdav/ wird automatisch hinzugefügt)" +"Für Dropbox leer lassen, für Nextcloud Server-URL angeben " +"(/remote.php/webdav/ wird automatisch hinzugefügt)" #: .\cookbook\forms.py:263 msgid "Search String" @@ -194,7 +198,7 @@ msgstr "Suchwort" #: .\cookbook\forms.py:280 msgid "File ID" -msgstr "Datei ID" +msgstr "Datei-ID" #: .\cookbook\forms.py:299 msgid "You must provide at least a recipe or a title." @@ -203,23 +207,23 @@ msgstr "Mindestens ein Rezept oder ein Titel müssen angegeben werden." #: .\cookbook\forms.py:312 msgid "You can list default users to share recipes with in the settings." msgstr "" -"Benutzer, mit denen neue Rezepte standardmäßig geteilt werden sollen, können " -"in den Einstellungen angegeben werden." +"Benutzer, mit denen neue Rezepte standardmäßig geteilt werden sollen, können" +" in den Einstellungen angegeben werden." #: .\cookbook\forms.py:313 #: .\cookbook\templates\forms\edit_internal_recipe.html:377 msgid "" -"You can use markdown to format this field. See the docs here" +"You can use markdown to format this field. See the docs here" msgstr "" -"Markdown kann genutzt werden, um dieses Feld zu formatieren. Siehe hier für weitere Information." +"Markdown kann genutzt werden, um dieses Feld zu formatieren. Siehe hier für weitere Information." #: .\cookbook\forms.py:328 msgid "A username is not required, if left blank the new user can choose one." msgstr "" -"Kein Benutzername benötigt. Wenn leer gelassen, kann der neue Benutzer einen " -"wählen." +"Kein Benutzername benötigt. Wenn leer gelassen, kann der neue Benutzer einen" +" wählen." #: .\cookbook\helper\permission_helper.py:137 #: .\cookbook\helper\permission_helper.py:206 @@ -228,7 +232,7 @@ msgstr "" #: .\cookbook\helper\permission_helper.py:242 .\cookbook\views\data.py:32 #: .\cookbook\views\views.py:106 .\cookbook\views\views.py:218 msgid "You do not have the required permissions to view this page!" -msgstr "Du hast nicht die notwendigen Rechte, um diese Seite zu anzuzeigen!" +msgstr "Du hast nicht die notwendigen Rechte um diese Seite zu sehen!" #: .\cookbook\helper\permission_helper.py:151 msgid "You are not logged in and therefore cannot view this page!" @@ -249,8 +253,8 @@ msgstr "" #: .\cookbook\helper\recipe_url_import.py:53 msgid "" -"The requested site does not provide any recognized data format to import the " -"recipe from." +"The requested site does not provide any recognized data format to import the" +" recipe from." msgstr "" "Die angefragte Seite stellt keine bekannten Datenformate zur Verfügung." @@ -263,24 +267,24 @@ msgid "" "Importer expected a .zip file. Did you choose the correct importer type for " "your data ?" msgstr "" +"Importer erwartet eine .zip Datei. Hast du den richtigen Importer-Typ für " +"deine Daten ausgewählt?" #: .\cookbook\integration\safron.py:23 #: .\cookbook\templates\forms\edit_internal_recipe.html:65 #: .\cookbook\templates\include\log_cooking.html:16 #: .\cookbook\templates\url_import.html:65 msgid "Servings" -msgstr "Portionen" +msgstr "Portion(en)" #: .\cookbook\integration\safron.py:25 -#, fuzzy -#| msgid "Waiting time ~" msgid "Waiting time" -msgstr "Wartezeit ~" +msgstr "Wartezeit" #: .\cookbook\integration\safron.py:27 #: .\cookbook\templates\forms\edit_internal_recipe.html:59 msgid "Preparation Time" -msgstr "Vorbereitungs Zeit" +msgstr "Vorbereitungszeit" #: .\cookbook\integration\safron.py:29 .\cookbook\templates\base.html:67 #: .\cookbook\templates\forms\ingredients.html:7 @@ -289,10 +293,8 @@ msgid "Cookbook" msgstr "Kochbuch" #: .\cookbook\integration\safron.py:31 -#, fuzzy -#| msgid "Nutrition" msgid "Section" -msgstr "Nährwert" +msgstr "Sektion" #: .\cookbook\migrations\0047_auto_20200602_1133.py:12 msgid "Breakfast" @@ -318,7 +320,7 @@ msgstr "Suche" #: .\cookbook\templates\meal_plan.html:5 .\cookbook\views\delete.py:165 #: .\cookbook\views\edit.py:216 .\cookbook\views\new.py:189 msgid "Meal-Plan" -msgstr "Plan" +msgstr "Essensplan" #: .\cookbook\models.py:79 .\cookbook\templates\base.html:78 msgid "Books" @@ -378,47 +380,45 @@ msgstr "Zur Hauptseite" #: .\cookbook\templates\404.html:35 msgid "Report a Bug" -msgstr "Einen Bug melden" +msgstr "Fehler melden" #: .\cookbook\templates\account\login.html:7 #: .\cookbook\templates\base.html:166 msgid "Login" -msgstr "Einloggen" +msgstr "Anmelden" #: .\cookbook\templates\account\login.html:13 #: .\cookbook\templates\account\login.html:28 msgid "Sign In" -msgstr "" +msgstr "Einloggen" #: .\cookbook\templates\account\login.html:38 msgid "Social Login" -msgstr "" +msgstr "Social Login" #: .\cookbook\templates\account\login.html:39 msgid "You can use any of the following providers to sign in." -msgstr "" +msgstr "Du kannst jeden der folgenden Anbieter zum Einloggen verwenden." #: .\cookbook\templates\account\logout.html:5 #: .\cookbook\templates\account\logout.html:9 #: .\cookbook\templates\account\logout.html:18 msgid "Sign Out" -msgstr "" +msgstr "Ausloggen" #: .\cookbook\templates\account\logout.html:11 -#, fuzzy -#| msgid "Are you sure that you want to merge these two units?" msgid "Are you sure you want to sign out?" -msgstr "Bist du sicher diese beiden Einheiten zusammengeführt werden sollen ?" +msgstr "Willst du dich wirklich ausloggen?" #: .\cookbook\templates\account\password_reset.html:5 #: .\cookbook\templates\account\password_reset_done.html:5 msgid "Password Reset" -msgstr "" +msgstr "Passwort Reset" #: .\cookbook\templates\account\password_reset.html:9 #: .\cookbook\templates\account\password_reset_done.html:9 msgid "Password reset is not implemented for the time being!" -msgstr "" +msgstr "Passwort-Rücksetzung ist derzeit noch nicht implementiert!" #: .\cookbook\templates\account\signup.html:5 msgid "Register" @@ -465,7 +465,7 @@ msgstr "Speicherquellen" #: .\cookbook\templates\base.html:111 msgid "Configure Sync" -msgstr "Sync einstellen" +msgstr "Synchronisation einstellen" #: .\cookbook\templates\base.html:113 msgid "Discovered Recipes" @@ -473,7 +473,7 @@ msgstr "Entdeckte Rezepte" #: .\cookbook\templates\base.html:115 msgid "Discovery Log" -msgstr "Entdeckungs-Log" +msgstr "Entdeckungsverlauf" #: .\cookbook\templates\base.html:117 .\cookbook\templates\stats.html:10 msgid "Statistics" @@ -485,7 +485,7 @@ msgstr "Einheiten & Zutaten" #: .\cookbook\templates\base.html:121 msgid "Import Recipe" -msgstr "Importiere Rezept" +msgstr "Rezept importieren" #: .\cookbook\templates\base.html:140 .\cookbook\templates\settings.html:6 #: .\cookbook\templates\settings.html:16 @@ -495,7 +495,7 @@ msgstr "Einstellungen" #: .\cookbook\templates\base.html:142 .\cookbook\templates\history.html:6 #: .\cookbook\templates\history.html:14 msgid "History" -msgstr "Geschichte" +msgstr "Verlauf" #: .\cookbook\templates\base.html:146 .\cookbook\templates\system.html:13 msgid "System" @@ -507,7 +507,7 @@ msgstr "Admin" #: .\cookbook\templates\base.html:152 msgid "Markdown Guide" -msgstr "Markdown-Hilfe" +msgstr "Markdown-Anleitung" #: .\cookbook\templates\base.html:154 msgid "GitHub" @@ -519,7 +519,7 @@ msgstr "API Browser" #: .\cookbook\templates\base.html:161 msgid "Logout" -msgstr "Ausloggen" +msgstr "Abmelden" #: .\cookbook\templates\batch\edit.html:6 msgid "Batch edit Category" @@ -544,10 +544,6 @@ msgid "Manage watched Folders" msgstr "Überwachte Ordner verwalten" #: .\cookbook\templates\batch\monitor.html:14 -#, fuzzy -#| msgid "" -#| "On this Page you can manage all storage folder locations that should be " -#| "monitored and synced" msgid "" "On this Page you can manage all storage folder locations that should be " "monitored and synced." @@ -574,7 +570,7 @@ msgid "" "please wait." msgstr "" "Abhängig von der Anzahl der Rezepte kann dieser Vorgang einige Minuten " -"dauern, bitte warten." +"dauern, bitte gedulde dich ein wenig." #: .\cookbook\templates\books.html:5 .\cookbook\templates\books.html:11 msgid "Recipe Books" @@ -600,17 +596,17 @@ msgstr "Zuletzt gekocht" #: .\cookbook\templates\books.html:71 msgid "There are no recipes in this book yet." -msgstr "In diesem Buch sind bisher keine Rezepte." +msgstr "In diesem Buch sind bisher noch keine Rezepte." #: .\cookbook\templates\export.html:6 .\cookbook\templates\test2.html:6 msgid "Export Recipes" -msgstr "Exportiere Rezepte" +msgstr "Rezepte exportieren" #: .\cookbook\templates\export.html:14 .\cookbook\templates\export.html:20 #: .\cookbook\templates\shopping_list.html:345 #: .\cookbook\templates\test2.html:14 .\cookbook\templates\test2.html:20 msgid "Export" -msgstr "Export" +msgstr "Exportieren" #: .\cookbook\templates\forms\edit_import_recipe.html:5 #: .\cookbook\templates\forms\edit_import_recipe.html:9 @@ -640,24 +636,20 @@ msgid "Waiting Time" msgstr "Wartezeit" #: .\cookbook\templates\forms\edit_internal_recipe.html:68 -#, fuzzy -#| msgid "Servings" msgid "Servings Text" -msgstr "Portionen" +msgstr "Portionen-Text" #: .\cookbook\templates\forms\edit_internal_recipe.html:79 msgid "Select Keywords" -msgstr "Schlagwort wählen" +msgstr "Schlagwörter wählen" #: .\cookbook\templates\forms\edit_internal_recipe.html:93 -#, fuzzy -#| msgid "Nutrition" msgid "Description" -msgstr "Nährwert" +msgstr "Beschreibung" #: .\cookbook\templates\forms\edit_internal_recipe.html:108 msgid "Nutrition" -msgstr "Nährwert" +msgstr "Nährwerte" #: .\cookbook\templates\forms\edit_internal_recipe.html:112 #: .\cookbook\templates\forms\edit_internal_recipe.html:162 @@ -674,7 +666,7 @@ msgstr "Kohlenhydrate" #: .\cookbook\templates\forms\edit_internal_recipe.html:122 msgid "Fats" -msgstr "Fett" +msgstr "Fette" #: .\cookbook\templates\forms\edit_internal_recipe.html:124 msgid "Proteins" @@ -691,7 +683,7 @@ msgstr "Als Überschrift anzeigen" #: .\cookbook\templates\forms\edit_internal_recipe.html:173 msgid "Hide as header" -msgstr "nicht als Überschrift anzeigen" +msgstr "Nicht als Überschrift anzeigen" #: .\cookbook\templates\forms\edit_internal_recipe.html:178 msgid "Move Up" @@ -716,7 +708,7 @@ msgstr "Zeit in Minuten" #: .\cookbook\templates\forms\edit_internal_recipe.html:261 #: .\cookbook\templates\shopping_list.html:181 msgid "Select Unit" -msgstr "Einheit auswählen" +msgstr "Einheit wählen" #: .\cookbook\templates\forms\edit_internal_recipe.html:262 #: .\cookbook\templates\forms\edit_internal_recipe.html:286 @@ -734,12 +726,12 @@ msgstr "Erstellen" #: .\cookbook\templates\url_import.html:105 #: .\cookbook\templates\url_import.html:137 msgid "Select" -msgstr "Wählen" +msgstr "Auswählen" #: .\cookbook\templates\forms\edit_internal_recipe.html:285 #: .\cookbook\templates\shopping_list.html:203 msgid "Select Food" -msgstr "Zutat wählen" +msgstr "Zutat auswählen" #: .\cookbook\templates\forms\edit_internal_recipe.html:302 #: .\cookbook\templates\meal_plan.html:256 @@ -753,11 +745,11 @@ msgstr "Zutat löschen" #: .\cookbook\templates\forms\edit_internal_recipe.html:325 msgid "Make Header" -msgstr "Überschrift machen" +msgstr "Überschrift erstellen" #: .\cookbook\templates\forms\edit_internal_recipe.html:331 msgid "Make Ingredient" -msgstr "Zutat machen" +msgstr "Zutat erstellen" #: .\cookbook\templates\forms\edit_internal_recipe.html:337 msgid "Disable Amount" @@ -769,7 +761,7 @@ msgstr "Menge aktivieren" #: .\cookbook\templates\forms\edit_internal_recipe.html:348 msgid "Copy Template Reference" -msgstr "" +msgstr "Kopiere Vorlagen-Referenz" #: .\cookbook\templates\forms\edit_internal_recipe.html:374 #: .\cookbook\templates\url_import.html:177 @@ -812,24 +804,20 @@ msgstr "Schritte" #: .\cookbook\templates\forms\ingredients.html:15 msgid "Edit Ingredients" -msgstr "Zutaten Bearbeiten" +msgstr "Zutaten bearbeiten" #: .\cookbook\templates\forms\ingredients.html:16 msgid "" "\n" -" The following form can be used if, accidentally, two (or more) units " -"or ingredients where created that should be\n" +" The following form can be used if, accidentally, two (or more) units or ingredients where created that should be\n" " the same.\n" -" It merges two units or ingredients and updates all recipes using " -"them.\n" +" It merges two units or ingredients and updates all recipes using them.\n" " " msgstr "" "\n" -" Dieses Formular kann genutzt werden wenn versehentlich zwei (oder " -"mehr) Einheitenoder Zutaten erstellt wurden die eigentlich identisch\n" +" Dieses Formular kann genutzt werden, wenn versehentlich zwei (oder mehr) Einheiten oder Zutaten erstellt wurden, die eigentlich identisch\n" " sein sollen.\n" -" Es vereint zwei Zutaten oder Einheiten und aktualisiert alle " -"entsprechenden Rezepte.\n" +" Es vereint zwei Zutaten oder Einheiten und aktualisiert alle entsprechenden Rezepte.\n" " " #: .\cookbook\templates\forms\ingredients.html:24 @@ -839,7 +827,8 @@ msgstr "Einheiten" #: .\cookbook\templates\forms\ingredients.html:26 msgid "Are you sure that you want to merge these two units?" -msgstr "Bist du sicher diese beiden Einheiten zusammengeführt werden sollen ?" +msgstr "" +"Bist du dir sicher, dass du diese beiden Einheiten zusammenführen möchtest?" #: .\cookbook\templates\forms\ingredients.html:31 #: .\cookbook\templates\forms\ingredients.html:40 @@ -848,13 +837,14 @@ msgstr "Zusammenführen" #: .\cookbook\templates\forms\ingredients.html:36 msgid "Are you sure that you want to merge these two ingredients?" -msgstr "Bist du sicher diese beiden Zutaten zusammengeführt werden sollen ?" +msgstr "" +"Bist du dir sicher, dass du diese beiden Zutaten zusammenführen möchtest?" #: .\cookbook\templates\generic\delete_template.html:18 -#, fuzzy, python-format -#| msgid "Are you sure you want to delete the %(title)s: %(object)s?" +#, python-format msgid "Are you sure you want to delete the %(title)s: %(object)s " -msgstr "Bist du sicher das %(title)s: %(object)s gelöscht werden soll " +msgstr "" +"Bist du sicher, dass %(title)s: %(object)s gelöscht werden soll?" #: .\cookbook\templates\generic\delete_template.html:21 msgid "Confirm" @@ -862,7 +852,7 @@ msgstr "Bestätigen" #: .\cookbook\templates\generic\edit_template.html:30 msgid "View" -msgstr "Angucken" +msgstr "Anschauen" #: .\cookbook\templates\generic\edit_template.html:34 msgid "Delete original file" @@ -899,26 +889,26 @@ msgstr "nächste" #: .\cookbook\templates\history.html:20 msgid "View Log" -msgstr "Aufruf Log" +msgstr "Anschau-Verlauf" #: .\cookbook\templates\history.html:24 msgid "Cook Log" -msgstr "Koch Log" +msgstr "Kochverlauf" #: .\cookbook\templates\import.html:6 .\cookbook\templates\test.html:6 msgid "Import Recipes" -msgstr "Importierte Rezepte" +msgstr "Rezepte importieren" #: .\cookbook\templates\import.html:14 .\cookbook\templates\import.html:20 #: .\cookbook\templates\test.html:14 .\cookbook\templates\test.html:20 #: .\cookbook\templates\url_import.html:211 .\cookbook\views\delete.py:60 #: .\cookbook\views\edit.py:182 msgid "Import" -msgstr "Rezept Importieren" +msgstr "Importieren" #: .\cookbook\templates\include\log_cooking.html:7 msgid "Log Recipe Cooking" -msgstr "Kochen Protokollieren" +msgstr "Kochen protokollieren" #: .\cookbook\templates\include\log_cooking.html:13 msgid "All fields are optional and can be left empty." @@ -953,28 +943,21 @@ msgstr "Sicherheitswarnung" #: .\cookbook\templates\include\storage_backend_warning.html:5 msgid "" "\n" -" The Password and Token field are stored as plain text " -"inside the database.\n" -" This is necessary because they are needed to make API requests, but " -"it also increases the risk of\n" +" The Password and Token field are stored as plain text inside the database.\n" +" This is necessary because they are needed to make API requests, but it also increases the risk of\n" " someone stealing it.
\n" -" To limit the possible damage tokens or accounts with limited access " -"can be used.\n" +" To limit the possible damage tokens or accounts with limited access can be used.\n" " " msgstr "" "\n" -" Das Password und Token werden im Klartext in der " -"Datenbank gespeichert.\n" -" Dies ist notwendig da Passwort oder Token benötigt werden um API " -"anfragen zu machen, bringt jedoch auch ein Sicherheitsrisiko mit sich.
\n" -" Um das Risiko zu minimieren sollten, wenn möglich, Tokens benutzt " -"oder Accounts mit limitiertem Zugriff verwendet werden.\n" +" Password und Token werden im Klartext in der Datenbank gespeichert.\n" +" Dies ist notwendig da Passwort oder Token benötigt werden, um API-Anfragen zu stellen, bringt jedoch auch ein Sicherheitsrisiko mit sich.
\n" +" Um das Risiko zu minimieren sollten, wenn möglich, Tokens oder Accounts mit limitiertem Zugriff verwendet werden.\n" " " #: .\cookbook\templates\index.html:29 msgid "Search recipe ..." -msgstr "Suche Rezept ..." +msgstr "Rezept suchen..." #: .\cookbook\templates\index.html:44 msgid "New Recipe" @@ -982,7 +965,7 @@ msgstr "Neues Rezept" #: .\cookbook\templates\index.html:47 msgid "Website Import" -msgstr "Webseiten Import" +msgstr "Webseiten-Import" #: .\cookbook\templates\index.html:53 msgid "Advanced Search" @@ -1003,36 +986,25 @@ msgstr "Rezepte" #: .\cookbook\templates\index.html:94 msgid "Log in to view recipes" -msgstr "Einloggen um Rezepte anzusehen" +msgstr "Einloggen, um Rezepte anzusehen" #: .\cookbook\templates\markdown_info.html:5 #: .\cookbook\templates\markdown_info.html:13 msgid "Markdown Info" -msgstr "Markdown Info" +msgstr "Markdown-Übersicht" #: .\cookbook\templates\markdown_info.html:14 msgid "" "\n" -" Markdown is lightweight markup language that can be used to format " -"plain text easily.\n" -" This site uses the Python Markdown library to\n" -" convert your text into nice looking HTML. Its full markdown " -"documentation can be found\n" -" here.\n" -" An incomplete but most likely sufficient documentation can be found " -"below.\n" +" Markdown is lightweight markup language that can be used to format plain text easily.\n" +" This site uses the Python Markdown library to\n" +" convert your text into nice looking HTML. Its full markdown documentation can be found\n" +" here.\n" +" An incomplete but most likely sufficient documentation can be found below.\n" " " msgstr "" "\n" -"Markdown ist eine Schreibweise mit derer einfacher Text formatiert werden " -"kann. Diese Seite benutzt Python Markdown, eine Bibliothek die reinen Text in " -"schönes HTML umwandelt. Die komplette Dokumentation befindet sich hier. Die wichtigsten Formatierungszeichen befinden sich auch hier " -"auf dieser Seite." +"Markdown ist eine Schreibweise mit der Text einfach formatiert werden kann. Diese Seite benutzt Python Markdown, eine Bibliothek, die reinen Text in schönes HTML umwandelt. Die komplette Dokumentation befindet sich hier. Die wichtigsten Formatierungszeichen befinden sich hier auf dieser Seite." #: .\cookbook\templates\markdown_info.html:25 msgid "Headers" @@ -1045,7 +1017,7 @@ msgstr "Formatierung" #: .\cookbook\templates\markdown_info.html:56 #: .\cookbook\templates\markdown_info.html:72 msgid "Line breaks are inserted by adding two spaces after the end of a line" -msgstr "Zeilenumbrüchen entstehen durch zwei Leerzeichen am ende einer Zeile" +msgstr "Zeilenumbrüche entstehen durch zwei Leerzeichen am ende einer Zeile" #: .\cookbook\templates\markdown_info.html:57 #: .\cookbook\templates\markdown_info.html:73 @@ -1055,12 +1027,12 @@ msgstr "oder durch eine leere Zeile dazwischen." #: .\cookbook\templates\markdown_info.html:59 #: .\cookbook\templates\markdown_info.html:74 msgid "This text is bold" -msgstr "Dieser Text ist dick dargestellt" +msgstr "Dieser Text ist fett" #: .\cookbook\templates\markdown_info.html:60 #: .\cookbook\templates\markdown_info.html:75 msgid "This text is italic" -msgstr "Dieser Text ist kursiv dargestellt" +msgstr "Dieser Text ist kursiv" #: .\cookbook\templates\markdown_info.html:61 #: .\cookbook\templates\markdown_info.html:77 @@ -1076,8 +1048,8 @@ msgid "" "Lists can ordered or unorderd. It is important to leave a blank line " "before the list!" msgstr "" -"Liste können sortiert oder unsortiert sein. Es ist wichtig das eine leere " -"Zeile vor der Liste frei gelassen wird!" +"Liste können sortiert oder unsortiert sein. Es ist wichtig das eine leere" +" Zeile vor der Liste frei gelassen wird!" #: .\cookbook\templates\markdown_info.html:87 #: .\cookbook\templates\markdown_info.html:108 @@ -1105,7 +1077,7 @@ msgstr "Ungeordnete Liste" #: .\cookbook\templates\markdown_info.html:117 #: .\cookbook\templates\markdown_info.html:118 msgid "ordered list item" -msgstr "Geordneter Listen Eintrag" +msgstr "Geordneter Listeneintrag" #: .\cookbook\templates\markdown_info.html:125 msgid "Images & Links" @@ -1116,32 +1088,28 @@ msgid "" "Links can be formatted with Markdown. This application also allows to paste " "links directly into markdown fields without any formatting." msgstr "" -"Links können mit Markdown formatiert werden aber es ist auch möglich Links " -"vollständig ohne Formatierung einzufügen." +"Links können mit Markdown formatiert werden, aber es ist auch möglich, Links" +" vollständig ohne Formatierung einzufügen." #: .\cookbook\templates\markdown_info.html:132 #: .\cookbook\templates\markdown_info.html:145 msgid "This will become an image" -msgstr "Dieser Text hier wird ein Bild werden" +msgstr "Dies wird ein Bild werden" #: .\cookbook\templates\markdown_info.html:152 msgid "Tables" msgstr "Tabellen" #: .\cookbook\templates\markdown_info.html:153 -#, fuzzy -#| msgid "" -#| "Markdown tables are hard to create by hand. It is recommended to use a " -#| "table editor like this one." msgid "" -"Markdown tables are hard to create by hand. It is recommended to use a table " -"editor like this one." +"Markdown tables are hard to create by hand. It is recommended to use a table" +" editor like this one." msgstr "" -"Es ist schwierig Markdown Tabellen von Hand zu erstellen, daher bietet es " -"sich an Werkzeuge wie dieses hier zu verwenden." +"Es ist schwierig, Markdown-Tabellen von Hand zu erstellen. Daher bietet es " +"sich an, Werkzeuge wie dieses hier zu verwenden." #: .\cookbook\templates\markdown_info.html:155 #: .\cookbook\templates\markdown_info.html:157 @@ -1167,7 +1135,7 @@ msgstr "Neuer Eintrag" #: .\cookbook\templates\meal_plan.html:113 #: .\cookbook\templates\shopping_list.html:52 msgid "Search Recipe" -msgstr "Rezept Suchen" +msgstr "Rezept suchen" #: .\cookbook\templates\meal_plan.html:139 msgid "Title" @@ -1179,18 +1147,18 @@ msgstr "Notiz (optional)" #: .\cookbook\templates\meal_plan.html:143 msgid "" -"You can use markdown to format this field. See the docs here" +"You can use markdown to format this field. See the docs " +"here" msgstr "" -"Dieses Feld Unterstützt Markdown Formatierung. Siehe Dokumentation" +"Dieses Feld Unterstützt Markdown Formatierung. Siehe Dokumentation" #: .\cookbook\templates\meal_plan.html:147 #: .\cookbook\templates\meal_plan.html:251 -#, fuzzy -#| msgid "Servings" msgid "Serving Count" -msgstr "Portionen" +msgstr "Anzahl Portionen" #: .\cookbook\templates\meal_plan.html:153 msgid "Create only note" @@ -1205,7 +1173,7 @@ msgstr "Einkaufsliste" #: .\cookbook\templates\meal_plan.html:172 msgid "Shopping list currently empty" -msgstr "Einkaufsliste aktuell leer" +msgstr "Die Einkaufsliste ist aktuell leer" #: .\cookbook\templates\meal_plan.html:175 msgid "Open Shopping List" @@ -1217,7 +1185,7 @@ msgstr "Plan" #: .\cookbook\templates\meal_plan.html:196 msgid "Number of Days" -msgstr "Anzahl Tage" +msgstr "Anzahl an Tagen" #: .\cookbook\templates\meal_plan.html:206 msgid "Weekday offset" @@ -1225,16 +1193,16 @@ msgstr "Wochentage verschieben" #: .\cookbook\templates\meal_plan.html:209 msgid "" -"Number of days starting from the first day of the week to offset the default " -"view." +"Number of days starting from the first day of the week to offset the default" +" view." msgstr "" -"Anzahl der Tage von ersten Tag der Woche die der Plan standardmäßig " +"Anzahl der Tage von ersten Tag der Woche, die der Plan standardmäßig " "verschoben sein soll." #: .\cookbook\templates\meal_plan.html:217 #: .\cookbook\templates\meal_plan.html:294 msgid "Edit plan types" -msgstr "Plan Typen editieren" +msgstr "Plantypen editieren" #: .\cookbook\templates\meal_plan.html:219 msgid "Show help" @@ -1265,103 +1233,42 @@ msgstr "Neue Mahlzeit" #: .\cookbook\templates\meal_plan.html:338 msgid "Meal Plan Help" -msgstr "Plan Hilfe" +msgstr "Plan-Hilfe" #: .\cookbook\templates\meal_plan.html:344 -#, fuzzy -#| msgid "" -#| "\n" -#| "

The meal plan module allows planning of " -#| "meals both with recipes or just notes.

\n" -#| "

Simply select a recipe from the list of " -#| "recently viewed recipes or search the one you\n" -#| " want and drag it to the desired plan " -#| "position. You can also add a note and a title and\n" -#| " then drag the recipe to create a plan " -#| "entry with a custom title and note. Creating only\n" -#| " Notes is possible by dragging the create " -#| "note box into the plan.

\n" -#| "

Click on a recipe in order to open the " -#| "detail view. Here you can also add it to the\n" -#| " shopping list. You can also add all " -#| "recipes of a day to the shopping list by\n" -#| " clicking the shopping cart at the top of " -#| "the table.

\n" -#| "

Since a common use case is to plan meals " -#| "together you can define\n" -#| " users you want to share your plan with in " -#| "the settings.\n" -#| "

\n" -#| "

You can also edit the types of meals you " -#| "want to plan. If you share your plan with\n" -#| " someone with\n" -#| " different meals, their meal types will " -#| "appear in your list as well. To prevent\n" -#| " duplicates (e.g. Other and Misc.)\n" -#| " name your meal types the same as the " -#| "users you share your meals with and they will be\n" -#| " merged.

\n" -#| " " msgid "" "\n" -"

The meal plan module allows planning of meals " -"both with recipes and notes.

\n" -"

Simply select a recipe from the list of " -"recently viewed recipes or search the one you\n" -" want and drag it to the desired plan " -"position. You can also add a note and a title and\n" -" then drag the recipe to create a plan entry " -"with a custom title and note. Creating only\n" -" Notes is possible by dragging the create " -"note box into the plan.

\n" -"

Click on a recipe in order to open the " -"detailed view. There you can also add it to the\n" -" shopping list. You can also add all recipes " -"of a day to the shopping list by\n" -" clicking the shopping cart at the top of the " -"table.

\n" -"

Since a common use case is to plan meals " -"together you can define\n" -" users you want to share your plan with in " -"the settings.\n" +"

The meal plan module allows planning of meals both with recipes and notes.

\n" +"

Simply select a recipe from the list of recently viewed recipes or search the one you\n" +" want and drag it to the desired plan position. You can also add a note and a title and\n" +" then drag the recipe to create a plan entry with a custom title and note. Creating only\n" +" Notes is possible by dragging the create note box into the plan.

\n" +"

Click on a recipe in order to open the detailed view. There you can also add it to the\n" +" shopping list. You can also add all recipes of a day to the shopping list by\n" +" clicking the shopping cart at the top of the table.

\n" +"

Since a common use case is to plan meals together you can define\n" +" users you want to share your plan with in the settings.\n" "

\n" -"

You can also edit the types of meals you want " -"to plan. If you share your plan with\n" +"

You can also edit the types of meals you want to plan. If you share your plan with\n" " someone with\n" -" different meals, their meal types will " -"appear in your list as well. To prevent\n" +" different meals, their meal types will appear in your list as well. To prevent\n" " duplicates (e.g. Other and Misc.)\n" -" name your meal types the same as the users " -"you share your meals with and they will be\n" +" name your meal types the same as the users you share your meals with and they will be\n" " merged.

\n" " " msgstr "" "\n" -"

Das Plan Modul erlaubt das Planen von " -"Rezepten oder auch nur Notizen.

\n" -"

Einfach ein Rezept raussuchen und an die " -"Stelle im Plan ziehen an der es gekocht werden soll. Es kann außerdem eine " -"Notiz und ein Titel hinzugefügt werden. Einen Eintrag nur als Notiz zu " -"erstellen ist durch Eingabe einer Notiz und schieben des Notiz Blocks in den " -"Plan möglich.

\n" -"

Durch klicken auf ein Rezept öffnet sich die " -"Detailansicht. Hier kann es auch auf die Einkaufsliste hinzugefügt werden. " -"Es können auch alle Rezepte eines Tages auf die Einkaufsliste gesetzt werden " -"indem der Einkaufswagen in der Tabelle angeklickt wird.

\n" -"

Da Pläne häufig für mehrere Nutzer erstellt " -"werden können andere Nutzer in den Einstellungen angegeben werden mit denen " -"neue Pläne automatisch geteilt werden sollen.\n" +"

Das Planmodul erlaubt das Planen mithilfe von Rezepten und Notizen.

\n" +"

Einfach ein Rezept aussuchen und an die Stelle im Plan ziehen, an der es gekocht werden soll. Es kann außerdem eine Notiz und ein Titel hinzugefügt werden. Einen Eintrag nur als Notiz zu erstellen ist durch Eingabe einer Notiz und Schieben des Notiz-Blocks in den Plan möglich.

\n" +"

Durch Klicken auf ein Rezept öffnet sich die Detailansicht. Da kann das Rezept auch auf die Einkaufsliste hinzugefügt werden. Es können auch alle Rezepte eines Tages auf die Einkaufsliste gesetzt werden, indem der Einkaufswagen im Tabellenkopf angeklickt wird.

\n" +"

Da Pläne häufig für mehrere Nutzer erstellt werden, können Nutzer in den Einstellungen angegeben werden, mit denen neue Pläne automatisch geteilt werden sollen.\n" "

\n" -"

Die Mahlzeiten die geplant werden sollen " -"können bearbeitet werden. Wenn Pläne zwischen Nutzern mit unterschiedlichen " -"Mahlzeiten geteilt werden erscheinen alle Mahlzeiten. Um Duplikate zu " -"vermeiden (z.B. Mittagessen und Mittag) sollten Mahlzeiten teilender Nutzer " -"gleich benannt werden, dadurch kann das System sie zusammenfassen.

\n" +"

Die Mahlzeiten, die geplant werden sollen, können bearbeitet werden. Wenn Pläne zwischen Nutzern mit unterschiedlichen Mahlzeiten geteilt werden, erscheinen alle Mahlzeiten. Um Duplikate zu vermeiden (z.B. Mittagessen und Mittag) sollten Mahlzeiten teilender Nutzer gleich benannt werden, dadurch kann das System sie zusammenfassen.

\n" " " #: .\cookbook\templates\meal_plan_entry.html:6 msgid "Meal Plan View" -msgstr "Plan Ansicht" +msgstr "Plan-Ansicht" #: .\cookbook\templates\meal_plan_entry.html:50 msgid "Never cooked before." @@ -1374,27 +1281,31 @@ msgstr "Andere Mahlzeiten an diesem Tag" #: .\cookbook\templates\no_groups_info.html:5 #: .\cookbook\templates\offline.html:6 msgid "Offline" -msgstr "" +msgstr "Offline" #: .\cookbook\templates\no_groups_info.html:12 msgid "No Permissions" -msgstr "" +msgstr "Keine Berechtigungen" #: .\cookbook\templates\no_groups_info.html:15 msgid "" "You do not have any groups and therefor cannot use this application. Please " "contact your administrator." msgstr "" +"Du hast keine Gruppe und kannst daher diese Anwendung nicht nutzen. Bitte " +"kontaktiere deinen Administrator." #: .\cookbook\templates\offline.html:19 msgid "You are currently offline!" -msgstr "" +msgstr "Du bist gerade offline!" #: .\cookbook\templates\offline.html:20 msgid "" "The recipes listed below are available for offline viewing because you have " "recently viewed them. Keep in mind that data might be outdated." msgstr "" +"Die unterhalb aufgelisteten Rezepte sind offline verfügbar, da du sie vor " +"kurzem angesehen hast. Beachte, dass die Daten veraltetet sein könnten." #: .\cookbook\templates\recipe_view.html:21 .\cookbook\templates\stats.html:47 msgid "Comments" @@ -1409,7 +1320,7 @@ msgstr "Kommentar" #: .\cookbook\templates\recipes_table.html:23 #: .\cookbook\templates\url_import.html:50 msgid "Recipe Image" -msgstr "Rezept Bild" +msgstr "Rezeptbild" #: .\cookbook\templates\recipes_table.html:46 #: .\cookbook\templates\url_import.html:55 @@ -1427,11 +1338,11 @@ msgstr "Extern" #: .\cookbook\templates\recipes_table.html:81 msgid "Log Cooking" -msgstr "Kochen Protokollieren" +msgstr "Kochen protokollieren" #: .\cookbook\templates\rest_framework\api.html:5 msgid "Recipe Home" -msgstr "Rezept Hauptseite" +msgstr "Rezept-Hauptseite" #: .\cookbook\templates\settings.html:22 msgid "Account" @@ -1439,7 +1350,7 @@ msgstr "Account" #: .\cookbook\templates\settings.html:38 msgid "Link social account" -msgstr "" +msgstr "Social Account verlinken" #: .\cookbook\templates\settings.html:42 msgid "Language" @@ -1451,22 +1362,22 @@ msgstr "Stil" #: .\cookbook\templates\settings.html:79 msgid "API Token" -msgstr "API Token" +msgstr "API-Token" #: .\cookbook\templates\settings.html:80 msgid "" "You can use both basic authentication and token based authentication to " "access the REST API." msgstr "" -"Sowohl basic auth als auch token basierte Authentifizierung können für die " -"REST API verwendet werden." +"Sowohl Basic Authentication als auch tokenbasierte Authentifizierung können " +"für die REST-API verwendet werden." #: .\cookbook\templates\settings.html:92 msgid "" -"Use the token as an Authorization header prefixed by the word token as shown " -"in the following examples:" +"Use the token as an Authorization header prefixed by the word token as shown" +" in the following examples:" msgstr "" -"Benutzt das Token als Authorization header mit dem präfix token wie in " +"Nutz den Token als Authorization-Header mit der Präfix \"Token\" wie in " "folgendem Beispiel:" #: .\cookbook\templates\settings.html:94 @@ -1475,7 +1386,7 @@ msgstr "oder" #: .\cookbook\templates\setup.html:6 .\cookbook\templates\system.html:5 msgid "Cookbook Setup" -msgstr "Kochbuch Setup" +msgstr "Kochbuch-Setup" #: .\cookbook\templates\setup.html:14 msgid "Setup" @@ -1485,16 +1396,16 @@ msgstr "Setup" msgid "" "To start using this application you must first create a superuser account." msgstr "" -"Um diese Anwendung zu Benutzen muss zunächst ein Administrator erstellt " -"werden." +"Um diese Anwendung zu benutzen, muss zunächst ein Administrator-Account " +"erstellt werden." #: .\cookbook\templates\setup.html:20 msgid "Create Superuser account" -msgstr "Administrator Erstellen" +msgstr "Administrator-Account Erstellen" #: .\cookbook\templates\shopping_list.html:75 msgid "Shopping Recipes" -msgstr "Einkaufs Rezepte" +msgstr "Einkaufs-Rezepte" #: .\cookbook\templates\shopping_list.html:79 msgid "No recipes selected" @@ -1502,13 +1413,11 @@ msgstr "Keine Rezepte ausgewählt" #: .\cookbook\templates\shopping_list.html:145 msgid "Entry Mode" -msgstr "" +msgstr "Eintrags-Modus" #: .\cookbook\templates\shopping_list.html:153 -#, fuzzy -#| msgid "New Entry" msgid "Add Entry" -msgstr "Neuer Eintrag" +msgstr "Eintrag hinzufügen" #: .\cookbook\templates\shopping_list.html:168 msgid "Amount" @@ -1516,17 +1425,15 @@ msgstr "Menge" #: .\cookbook\templates\shopping_list.html:224 msgid "Supermarket" -msgstr "" +msgstr "Supermarkt" #: .\cookbook\templates\shopping_list.html:234 -#, fuzzy -#| msgid "Select User" msgid "Select Supermarket" -msgstr "Nutzer Auswählen" +msgstr "Supermarkt auswählen" #: .\cookbook\templates\shopping_list.html:258 msgid "Select User" -msgstr "Nutzer Auswählen" +msgstr "Nutzer auswählen" #: .\cookbook\templates\shopping_list.html:277 msgid "Finished" @@ -1534,7 +1441,7 @@ msgstr "Erledigt" #: .\cookbook\templates\shopping_list.html:290 msgid "You are offline, shopping list might not syncronize." -msgstr "Du bist offline, die Einkaufsliste aktualisiert möglicherweise nicht." +msgstr "Du bist offline, die Einkaufsliste wird ggf. nicht synchronisiert." #: .\cookbook\templates\shopping_list.html:353 msgid "Copy/Export" @@ -1542,35 +1449,38 @@ msgstr "Kopieren/Exportieren" #: .\cookbook\templates\shopping_list.html:357 msgid "List Prefix" -msgstr "Listen Präfix" +msgstr "Listenpräfix" #: .\cookbook\templates\shopping_list.html:696 msgid "There was an error creating a resource!" -msgstr "Es gab einen Fehler beim erstellen einer Ressource!" +msgstr "Es gab einen Fehler beim Erstellen einer Ressource!" #: .\cookbook\templates\socialaccount\connections.html:4 #: .\cookbook\templates\socialaccount\connections.html:7 msgid "Account Connections" -msgstr "" +msgstr "Account-Verbindungen" #: .\cookbook\templates\socialaccount\connections.html:10 msgid "" "You can sign in to your account using any of the following third party\n" " accounts:" msgstr "" +"Du kannst dich mit den folgenden Drittanbieter-Accounts\n" +" anmelden:" #: .\cookbook\templates\socialaccount\connections.html:36 msgid "Remove" -msgstr "" +msgstr "Entfernen" #: .\cookbook\templates\socialaccount\connections.html:44 msgid "" "You currently have no social network accounts connected to this account." msgstr "" +"Du hast momentan keine Social-Media Accounts mit diesem Account verbunden." #: .\cookbook\templates\socialaccount\connections.html:47 msgid "Add a 3rd Party Account" -msgstr "" +msgstr "Fremden Account hinzufügen" #: .\cookbook\templates\stats.html:4 msgid "Stats" @@ -1578,15 +1488,15 @@ msgstr "Statistiken" #: .\cookbook\templates\stats.html:19 msgid "Number of objects" -msgstr "Anzahl der Objekte" +msgstr "Anzahl an Objekten" #: .\cookbook\templates\stats.html:30 msgid "Recipe Imports" -msgstr "Rezept Importe" +msgstr "Importierte Rezepte" #: .\cookbook\templates\stats.html:38 msgid "Objects stats" -msgstr "Objekt Statistiken" +msgstr "Objekt-Statistiken" #: .\cookbook\templates\stats.html:41 msgid "Recipes without Keywords" @@ -1602,7 +1512,7 @@ msgstr "Interne Rezepte" #: .\cookbook\templates\system.html:21 .\cookbook\views\lists.py:128 msgid "Invite Links" -msgstr "Einladungs Link" +msgstr "Einladungslinks" #: .\cookbook\templates\system.html:22 msgid "Show Links" @@ -1618,29 +1528,25 @@ msgstr "Backup herunterladen" #: .\cookbook\templates\system.html:49 msgid "System Information" -msgstr "System Information" +msgstr "Systeminformation" #: .\cookbook\templates\system.html:51 msgid "" "\n" -" Django Recipes is an open source free software application. It can " -"be found on\n" +" Django Recipes is an open source free software application. It can be found on\n" " GitHub.\n" -" Changelogs can be found here.\n" +" Changelogs can be found here.\n" " " msgstr "" "\n" -" Django Rezepte ist eine kostenlose OpenSource Anwendung. Der Source " -"Code befindet sich auf\n" +" Django Recipes ist eine kostenlose OpenSource-Anwendung. Der Quellcode befindet sich auf\n" " GitHub.\n" -" Eine Übersicht über alle Änderungen findet sich hier.\n" +" Eine Übersicht über alle Änderungen findet sich hier.\n" " " #: .\cookbook\templates\system.html:65 msgid "Media Serving" -msgstr "Media Serving" +msgstr "Medien ausliefern" #: .\cookbook\templates\system.html:66 .\cookbook\templates\system.html:81 #: .\cookbook\templates\system.html:97 @@ -1656,22 +1562,19 @@ msgstr "Ok" msgid "" "Serving media files directly using gunicorn/python is not recommend!\n" " Please follow the steps described\n" -" here to update\n" +" here to update\n" " your installation.\n" " " msgstr "" -"Serving media files directly using gunicorn/python is not recommend!\n" -" Please follow the steps described\n" -" here to update\n" -" your installation.\n" -" " +"Das direkte ausliefern von Mediendateien mit gunicorn/python ist nicht " +"empfehlenswert! Bitte folge den beschriebenen Schritten hier," +" um Ihre Installation zu aktualisieren." #: .\cookbook\templates\system.html:74 .\cookbook\templates\system.html:90 #: .\cookbook\templates\system.html:105 .\cookbook\templates\system.html:119 msgid "Everything is fine!" -msgstr "Alles ok!" +msgstr "Alles in Ordnung!" #: .\cookbook\templates\system.html:79 msgid "Secret Key" @@ -1680,46 +1583,30 @@ msgstr "Secret Key" #: .\cookbook\templates\system.html:83 msgid "" "\n" -" You do not have a SECRET_KEY configured in your " -".env file. Django defaulted to the\n" +" You do not have a SECRET_KEY configured in your .env file. Django defaulted to the\n" " standard key\n" -" provided with the installation which is publicly know and " -"insecure! Please set\n" -" SECRET_KEY int the .env configuration " -"file.\n" +" provided with the installation which is publicly know and insecure! Please set\n" +" SECRET_KEY int the .env configuration file.\n" " " msgstr "" "\n" -" You do not have a SECRET_KEY configured in your " -".env file. Django defaulted to the\n" -" standard key\n" -" provided with the installation which is publicly know and " -"insecure! Please set\n" -" SECRET_KEY int the .env configuration " -"file.\n" -" " +"Du hast keinen SECRET_KEY in deiner .env-Datei konfiguriert. Django verwendet standardmäßig den mit der Installation gelieferten Standardschlüssel, der öffentlich bekannt und unsicher ist! Bitte setze den SECRET_KEY in der Konfigurationsdatei .env." #: .\cookbook\templates\system.html:95 msgid "Debug Mode" -msgstr "Debug Mode" +msgstr "Debug-Modus" #: .\cookbook\templates\system.html:99 msgid "" "\n" -" This application is still running in debug mode. This is most " -"likely not needed. Turn of debug mode by\n" +" This application is still running in debug mode. This is most likely not needed. Turn of debug mode by\n" " setting\n" -" DEBUG=0 int the .env configuration " -"file.\n" +" DEBUG=0 int the .env configuration file.\n" " " msgstr "" "\n" -" This application is still running in debug mode. This is most " -"likely not needed. Turn of debug mode by\n" -" setting\n" -" DEBUG=0 int the .env configuration " -"file.\n" -" " +"Diese Anwendung läuft noch im Debug-Modus. Dieser wird höchstwahrscheinlich nicht benötigt.\n" +"Schalte den Debug-Modus aus, indem du DEBUG=0 in der Konfigurationsdatei .env einstellst." #: .\cookbook\templates\system.html:110 msgid "Database" @@ -1727,33 +1614,30 @@ msgstr "Datenbank" #: .\cookbook\templates\system.html:112 msgid "Info" -msgstr "Information" +msgstr "Info" #: .\cookbook\templates\system.html:114 msgid "" "\n" -" This application is not running with a Postgres database " -"backend. This is ok but not recommended as some\n" +" This application is not running with a Postgres database backend. This is ok but not recommended as some\n" " features only work with postgres databases.\n" " " msgstr "" "\n" -" This application is not running with a Postgres database " -"backend. This is ok but not recommended as some\n" -" features only work with postgres databases.\n" -" " +"Diese Anwendung läuft nicht mit einer Postgres Datenbank. Dies ist in Ordnung, wird aber nicht empfohlen, da einige\n" +"Funktionen nur mit einer Postgres-Datenbanken funktionieren." #: .\cookbook\templates\url_import.html:5 msgid "URL Import" -msgstr "URL Import" +msgstr "URL-Import" #: .\cookbook\templates\url_import.html:23 msgid "Enter website URL" -msgstr "Webseiten URL eingeben" +msgstr "Webseite-URL eingeben" #: .\cookbook\templates\url_import.html:44 msgid "Recipe Name" -msgstr "Rezept Name" +msgstr "Rezeptname" #: .\cookbook\templates\url_import.html:104 #: .\cookbook\templates\url_import.html:136 @@ -1767,7 +1651,7 @@ msgstr "Alle Schlagwörter" #: .\cookbook\templates\url_import.html:206 msgid "Import all keywords, not only the ones already existing." -msgstr "Importiert alle Schlagwörter, nicht nur die die bereits existieren." +msgstr "Alle Schlagwörter importieren, nicht nur die bereits bestehenden." #: .\cookbook\templates\url_import.html:233 msgid "Information" @@ -1776,17 +1660,15 @@ msgstr "Information" #: .\cookbook\templates\url_import.html:235 msgid "" " Only websites containing ld+json or microdata information can currently\n" -" be imported. Most big recipe pages " -"support this. If you site cannot be imported but\n" +" be imported. Most big recipe pages support this. If you site cannot be imported but\n" " you think\n" -" it probably has some kind of structured " -"data feel free to post an example in the\n" +" it probably has some kind of structured data feel free to post an example in the\n" " github issues." msgstr "" "Nur Webseiten mit ld+json oder microdata können importiert werden. Die " "meisten großen Seiten unterstützen diese Formate. Wenn eine Seite nicht " -"importiert werden kann sie aber strukturierte Daten aufweist kann ein GitHub " -"Issue geöffnet werden." +"importiert werden kann, sie aber strukturierte Daten aufweist, kann ein " +"GitHub-Issue geöffnet werden." #: .\cookbook\templates\url_import.html:243 msgid "Google ld+json Info" @@ -1794,23 +1676,23 @@ msgstr "Google ld+json Informationen" #: .\cookbook\templates\url_import.html:246 msgid "GitHub Issues" -msgstr "GitHub Issues" +msgstr "GitHub-Issues" #: .\cookbook\templates\url_import.html:248 msgid "Recipe Markup Specification" -msgstr "Recipe Markup Spezifikation" +msgstr "Rezept-Markup-Spezifikation" #: .\cookbook\views\api.py:104 msgid "Parameter filter_list incorrectly formatted" -msgstr "Parameter filter_list incorrectly formatted" +msgstr "Der Parameter filter_list ist falsch formatiert" #: .\cookbook\views\api.py:117 msgid "Preference for given user already exists" -msgstr "Preference for given user already exists" +msgstr "Präferenz für den Benutzer existiert bereits" #: .\cookbook\views\api.py:416 .\cookbook\views\views.py:265 msgid "This feature is not available in the demo version!" -msgstr "" +msgstr "Diese Funktion ist in der Demo-Version nicht verfügbar!" #: .\cookbook\views\api.py:439 msgid "Sync successful!" @@ -1822,35 +1704,36 @@ msgstr "Fehler beim Synchronisieren" #: .\cookbook\views\api.py:510 msgid "The requested page could not be found." -msgstr "Die Angefragte Seite konnte nicht gefunden werden." +msgstr "Die angefragte Seite konnte nicht gefunden werden." #: .\cookbook\views\api.py:519 msgid "" "The requested page refused to provide any information (Status Code 403)." -msgstr "Die angefragte Seite hat die Anfrage abgelehnt (Status Code 403)." +msgstr "Die angefragte Seite hat die Anfrage abgelehnt (Status-Code 403)." #: .\cookbook\views\data.py:101 #, python-format msgid "Batch edit done. %(count)d recipe was updated." msgid_plural "Batch edit done. %(count)d Recipes where updated." -msgstr[0] "Massenbearbeitung erfolgreich. %(count)d Rezept wurde aktualisiert." +msgstr[0] "" +"Massenbearbeitung erfolgreich. %(count)d Rezept wurde aktualisiert." msgstr[1] "" "Massenbearbeitung erfolgreich. %(count)d Rezepte wurden aktualisiert." #: .\cookbook\views\delete.py:72 msgid "Monitor" -msgstr "Monitor" +msgstr "Überwachen" #: .\cookbook\views\delete.py:96 .\cookbook\views\lists.py:109 #: .\cookbook\views\new.py:83 msgid "Storage Backend" -msgstr "Speicher Quelle" +msgstr "Speicherquelle" #: .\cookbook\views\delete.py:106 msgid "" "Could not delete this storage backend as it is used in at least one monitor." msgstr "" -"Speicherquelle konnte nicht gelöscht werden da sie in mindestens einem " +"Speicherquelle konnte nicht gelöscht werden, da sie in mindestens einem " "Monitor verwendet wird." #: .\cookbook\views\delete.py:129 .\cookbook\views\edit.py:196 @@ -1880,7 +1763,7 @@ msgstr "Speicherquelle gespeichert!" #: .\cookbook\views\edit.py:137 msgid "There was an error updating this storage backend!" -msgstr "Es gab einen Fehler beim aktualisierung dieser Speicher Quelle!" +msgstr "Es gab einen Fehler beim Aktualisieren dieser Speicherquelle!" #: .\cookbook\views\edit.py:148 msgid "Storage" @@ -1900,27 +1783,27 @@ msgstr "Einheiten zusammengeführt!" #: .\cookbook\views\edit.py:295 .\cookbook\views\edit.py:317 msgid "Cannot merge with the same object!" -msgstr "" +msgstr "Zusammenführen mit selben Objekt nicht möglich!" #: .\cookbook\views\edit.py:311 msgid "Foods merged!" -msgstr "Lebensmittel vereint" +msgstr "Zutaten zusammengeführt!" #: .\cookbook\views\import_export.py:42 msgid "Importing is not implemented for this provider" -msgstr "" +msgstr "Importieren ist für diesen Anbieter noch nicht implementiert" #: .\cookbook\views\import_export.py:58 msgid "Exporting is not implemented for this provider" -msgstr "" +msgstr "Exportieren ist für diesen Anbieter noch nicht implementiert" #: .\cookbook\views\lists.py:42 msgid "Import Log" -msgstr "Import Log" +msgstr "Importverlauf" #: .\cookbook\views\lists.py:55 msgid "Discovery" -msgstr "Entdeckung" +msgstr "Entdecken" #: .\cookbook\views\lists.py:92 msgid "Shopping Lists" @@ -1928,16 +1811,16 @@ msgstr "Einkaufslisten" #: .\cookbook\views\new.py:107 msgid "Imported new recipe!" -msgstr "Importier neue Rezepte!" +msgstr "Neues Rezept importiert!" #: .\cookbook\views\new.py:114 msgid "There was an error importing this recipe!" -msgstr "Beim importieren des Rezeptes ist ein Fehler aufgetreten!" +msgstr "Beim Importieren des Rezeptes ist ein Fehler aufgetreten!" #: .\cookbook\views\views.py:117 msgid "You do not have the required permissions to perform this action!" msgstr "" -"Sie haben nicht die notwendigen Berechtigungen um diese Aktion durchzuführen!" +"Du hast nicht die notwendige Berechtigung, um diese Aktion durchzuführen!" #: .\cookbook\views\views.py:136 msgid "Comment saved!" @@ -1945,7 +1828,7 @@ msgstr "Kommentar gespeichert!" #: .\cookbook\views\views.py:152 msgid "This recipe is already linked to the book!" -msgstr "" +msgstr "Dieses Rezept ist bereits mit dem Buch verlinkt!" #: .\cookbook\views\views.py:158 msgid "Bookmark saved!" @@ -1954,11 +1837,11 @@ msgstr "Lesezeichen gespeichert!" #: .\cookbook\views\views.py:380 msgid "" "The setup page can only be used to create the first user! If you have " -"forgotten your superuser credentials please consult the django documentation " -"on how to reset passwords." +"forgotten your superuser credentials please consult the django documentation" +" on how to reset passwords." msgstr "" -"Die Setup Seite kann nur für den ersten Nutzer verwendet werden. Zum " -"zurücksetzen von Passwörtern bitte der Django Dokumentation folgen." +"Die Setup-Seite kann nur für den ersten Nutzer verwendet werden. Zum " +"Zurücksetzen von Passwörtern bitte der Django-Dokumentation folgen." #: .\cookbook\views\views.py:388 .\cookbook\views\views.py:435 msgid "Passwords dont match!" @@ -1970,163 +1853,8 @@ msgstr "Benutzer wurde erstellt, bitte einloggen!" #: .\cookbook\views\views.py:419 msgid "Malformed Invite Link supplied!" -msgstr "Fehlerhaften Einladungslink angegeben!" +msgstr "Fehlerhafter Einladungslink angegeben!" #: .\cookbook\views\views.py:470 msgid "Invite Link not valid or already used!" msgstr "Einladungslink ungültig oder bereits genutzt!" - -#~ msgid "Export Base64 encoded image?" -#~ msgstr "Base64 kodiertes Bild exportieren?" - -#~ msgid "Download export directly or show on page?" -#~ msgstr "Direkter Download oder Anzeige auf Seite ?" - -#~ msgid "Simply paste a JSON export into this textarea and click import." -#~ msgstr "Einfach JSON in die Textbox einfügen und \"Importieren\" klicken." - -#~ msgid "Exported Recipe" -#~ msgstr "Exportierte Rezepte" - -#~ msgid "Copy to clipboard" -#~ msgstr "In Zwischenablage kopieren" - -#~ msgid "Copied!" -#~ msgstr "Kopiert!" - -#~ msgid "Copy list to clipboard" -#~ msgstr "Kopiere Liste in Zwischenablage" - -#~ msgid "Your username and password didn't match. Please try again." -#~ msgstr "Nutzername oder Passwort falsch. Bitte versuch es erneut." - -#~ msgid "Recipe imported successfully!" -#~ msgstr "Rezept erfolgreich importiert!" - -#~ msgid "Something went wrong during the import!" -#~ msgstr "Beim Import ist etwas schief gegangen!" - -#~ msgid "Could not parse the supplied JSON!" -#~ msgstr "Das JSON konnte nicht gelesen werden!" - -#~ msgid "" -#~ "External recipes cannot be exported, please share the file directly or " -#~ "select an internal recipe." -#~ msgstr "" -#~ "Externe Rezepte können nicht exportiert werden, bitte Datei direkt teilen " -#~ "oder ein Internes Rezept auswählen." - -#~ msgid "Scaling factor for recipe." -#~ msgstr "Skalierungsfaktor für das Rezept." - -#~ msgid "Error" -#~ msgstr "Fehler" - -#~ msgid "There was an error loading the recipe!" -#~ msgstr "Es gab einen Fehler beim Laden des Rezepts!" - -#~ msgid "Updated" -#~ msgstr "Aktualisiert" - -#~ msgid "Changes saved successfully!" -#~ msgstr "Änderungen erfolgreich gespeichert!" - -#~ msgid "There was an error updating the recipe!" -#~ msgstr "Es gab einen Fehler beim aktualisieren des Rezepts!" - -#~ msgid "Are you sure that you want to delete this ingredient?" -#~ msgstr "Bist du sicher das du diese Zutat löschen willst?" - -#~ msgid "Are you sure that you want to delete this step?" -#~ msgstr "Soll dieser Schritt wirklich gelöscht werden?" - -#~ msgid "There was an error loading a resource!" -#~ msgstr "Es gab einen Fehler beim laden der Ressource!" - -#~ msgid "Recipe Multiplier" -#~ msgstr "Rezept Multiplikator" - -#~ msgid "" -#~ "When deleting a meal type all entries using that type will be deleted as " -#~ "well. Deletion will apply when configuration is saved. Do you want to " -#~ "proceed?" -#~ msgstr "" -#~ "Wenn eine Mahlzeit gelöscht wird werden auch alle Einträge mit dieser " -#~ "Mahlzeit gelöscht. Die Löschung wird erst aktiv wenn die Konfiguration " -#~ "gespeichert wird. Fortfahren ?" - -#~ msgid "Add to Book" -#~ msgstr "Zu Buch hinzufügen" - -#~ msgid "Add to Plan" -#~ msgstr "Zum Plan hinzufügen" - -#~ msgid "Print" -#~ msgstr "Drucken" - -#~ msgid "Share" -#~ msgstr "Teilen" - -#~ msgid "in" -#~ msgstr "in" - -#~ msgid "Preparation time ~" -#~ msgstr "Vorbereitungs Zeit ~" - -#~ msgid "Minutes" -#~ msgstr "Minuten" - -#~ msgid "View external recipe" -#~ msgstr "Externes Rezept ansehen" - -#~ msgid "External recipe image" -#~ msgstr "Externes Rezeptbild" - -#~ msgid "External recipe" -#~ msgstr "Externes Rezept" - -#~ msgid "" -#~ "\n" -#~ " This is an external recipe, which " -#~ "means you can only view it by opening the link\n" -#~ " above.\n" -#~ " You can convert this recipe to a " -#~ "fancy recipe by pressing the convert button. The\n" -#~ " original\n" -#~ " file\n" -#~ " will still be accessible.\n" -#~ " " -#~ msgstr "" -#~ "\n" -#~ " Dies ist ein externes Rezept. Das bedeutet das es " -#~ "nur durch klicken auf den link geöffnet werden kann.\n" -#~ " Das Rezept kann durch drücken des Umwandeln " -#~ "Knopfes in ein schickes lokales Rezept verwandelt werden. Die originale " -#~ "Datei bleibt weiterhin verfügbar.\n" -#~ " " - -#~ msgid "Convert now!" -#~ msgstr "Jetzt umwandeln!" - -#~ msgid "There was an error updating a resource!" -#~ msgstr "Es gab einen Fehler beim aktualisieren der Ressource!" - -#~ msgid "Object created successfully!" -#~ msgstr "Objekt erfolgreich erstellt!" - -#~ msgid "Please enter a valid food" -#~ msgstr "Bitte ein gültiges Lebensmittel eingeben" - -#~ msgid "Already importing the selected recipe, please wait!" -#~ msgstr "Das Rezept wird bereits importiert, bitte warten!" - -#~ msgid "An error occurred while trying to import this recipe!" -#~ msgstr "Beim importieren der Webseite ist ein Fehler aufgetreten!" - -#~ msgid "Default user to share newly created meal plan entries with." -#~ msgstr "" -#~ "Standardbenutzer, mit denen neue Einträge in der Mahlzeitenplanung " -#~ "geteilt werden sollen." - -#~ msgid "Tags" -#~ msgstr "Schlagwörter" From bccc41d177ec1c3e7878069333351b2e8711dee8 Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 22 Feb 2021 19:56:33 +0100 Subject: [PATCH 27/96] Add environment variable to include Sub-Path in resolve.js. --- docs/install/other.md | 3 ++- recipes/settings.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/install/other.md b/docs/install/other.md index 45b50a31..1221b209 100644 --- a/docs/install/other.md +++ b/docs/install/other.md @@ -35,6 +35,7 @@ docker-compose: environment: # all the other env - SCRIPT_NAME=/ + - JS_REVERSE_SCRIPT_PREFIX=// - STATIC_URL=//static/ - MEDIA_URL=//media/ labels: @@ -56,4 +57,4 @@ apache: I used two paths `` and `` for simplicity. In my case I have ` = recipes` and ` = serve/recipes`. One could also change the matching rules of traefik to have everything under one path. -I left out the TLS config in this example for simplicty. \ No newline at end of file +I left out the TLS config in this example for simplicty. diff --git a/recipes/settings.py b/recipes/settings.py index 3105c67f..8e39a3b4 100644 --- a/recipes/settings.py +++ b/recipes/settings.py @@ -228,6 +228,8 @@ LANGUAGES = [ # path for django_js_reverse to generate the javascript file containing all urls. Only done because the default command (collectstatic_js_reverse) fails to update the manifest JS_REVERSE_OUTPUT_PATH = os.path.join(BASE_DIR, "cookbook/static/django_js_reverse") +JS_REVERSE_SCRIPT_PREFIX = os.getenv('JS_REVERSE_SCRIPT_PREFIX', '') + STATIC_URL = os.getenv('STATIC_URL', '/static/') STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") From 7f391c25a443effc890e379a450db2e31f8fb66a Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Mon, 22 Feb 2021 19:59:43 +0100 Subject: [PATCH 28/96] fixed test --- cookbook/tests/other/test_edits_recipe.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) mode change 100644 => 100755 cookbook/tests/other/test_edits_recipe.py diff --git a/cookbook/tests/other/test_edits_recipe.py b/cookbook/tests/other/test_edits_recipe.py old mode 100644 new mode 100755 index 7394854c..a1ba3944 --- a/cookbook/tests/other/test_edits_recipe.py +++ b/cookbook/tests/other/test_edits_recipe.py @@ -11,15 +11,15 @@ class TestEditsRecipe(TestBase): def test_ld_json(self): test_list = [ {'file': 'cookbook/tests/resources/websites/ld_json_1.html', 'result_length': 3237}, - {'file': 'cookbook/tests/resources/websites/ld_json_2.html', 'result_length': 1510}, - {'file': 'cookbook/tests/resources/websites/ld_json_3.html', 'result_length': 1629}, + {'file': 'cookbook/tests/resources/websites/ld_json_2.html', 'result_length': 1525}, + {'file': 'cookbook/tests/resources/websites/ld_json_3.html', 'result_length': 1644}, {'file': 'cookbook/tests/resources/websites/ld_json_4.html', 'result_length': 1744}, - {'file': 'cookbook/tests/resources/websites/ld_json_itemList.html', 'result_length': 3206}, + {'file': 'cookbook/tests/resources/websites/ld_json_itemList.html', 'result_length': 3221}, {'file': 'cookbook/tests/resources/websites/ld_json_multiple.html', 'result_length': 1621}, - {'file': 'cookbook/tests/resources/websites/micro_data_1.html', 'result_length': 1079}, - {'file': 'cookbook/tests/resources/websites/micro_data_2.html', 'result_length': 1438}, - {'file': 'cookbook/tests/resources/websites/micro_data_3.html', 'result_length': 1148}, - {'file': 'cookbook/tests/resources/websites/micro_data_4.html', 'result_length': 4396}, + {'file': 'cookbook/tests/resources/websites/micro_data_1.html', 'result_length': 1094}, + {'file': 'cookbook/tests/resources/websites/micro_data_2.html', 'result_length': 1453}, + {'file': 'cookbook/tests/resources/websites/micro_data_3.html', 'result_length': 1163}, + {'file': 'cookbook/tests/resources/websites/micro_data_4.html', 'result_length': 4411}, ] for test in test_list: From 76c7ad1ff5e3d50b96f9746c58ff3498d62b5747 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Feb 2021 06:02:25 +0000 Subject: [PATCH 29/96] Bump django-autocomplete-light from 3.8.1 to 3.8.2 Bumps [django-autocomplete-light](https://github.com/yourlabs/django-autocomplete-light) from 3.8.1 to 3.8.2. - [Release notes](https://github.com/yourlabs/django-autocomplete-light/releases) - [Changelog](https://github.com/yourlabs/django-autocomplete-light/blob/master/CHANGELOG) - [Commits](https://github.com/yourlabs/django-autocomplete-light/commits) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 61dce5f9..0863dd30 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ bleach==3.3.0 bleach-whitelist==0.0.11 Django==3.1.6 django-annoying==0.10.6 -django-autocomplete-light==3.8.1 +django-autocomplete-light==3.8.2 django-cleanup==5.1.0 django-crispy-forms==1.11.0 django-emoji-picker==0.0.6 From 8dffc070723db4aa9453553cbe8b76556f503ec8 Mon Sep 17 00:00:00 2001 From: Alberto <3170731+albcp@users.noreply.github.com> Date: Tue, 23 Feb 2021 18:57:59 +0100 Subject: [PATCH 30/96] get JS_REVERSE_SCRIPT_PREFIX from SCRIPT_NAME --- recipes/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recipes/settings.py b/recipes/settings.py index 8e39a3b4..2fa62720 100644 --- a/recipes/settings.py +++ b/recipes/settings.py @@ -228,7 +228,7 @@ LANGUAGES = [ # path for django_js_reverse to generate the javascript file containing all urls. Only done because the default command (collectstatic_js_reverse) fails to update the manifest JS_REVERSE_OUTPUT_PATH = os.path.join(BASE_DIR, "cookbook/static/django_js_reverse") -JS_REVERSE_SCRIPT_PREFIX = os.getenv('JS_REVERSE_SCRIPT_PREFIX', '') +JS_REVERSE_SCRIPT_PREFIX = os.getenv('JS_REVERSE_SCRIPT_PREFIX', os.getenv('SCRIPT_NAME', '')) STATIC_URL = os.getenv('STATIC_URL', '/static/') STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") From 59cc22a877eef05354d29e3640627a332b32f6d7 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Tue, 23 Feb 2021 20:44:13 +0100 Subject: [PATCH 31/96] wip serializer permission --- cookbook/serializer.py | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 436f849d..7eb5523a 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -5,6 +5,7 @@ from drf_writable_nested import (UniqueFieldsMixin, WritableNestedModelSerializer) from rest_framework import serializers from rest_framework.exceptions import ValidationError +from rest_framework.serializers import BaseSerializer, Serializer from cookbook.models import (Comment, CookLog, Food, Ingredient, Keyword, MealPlan, MealType, NutritionInformation, Recipe, @@ -39,6 +40,12 @@ class CustomDecimalField(serializers.Field): raise ValidationError('A valid number is required') +class CreateWithSpaceMixin(Serializer): + def create(self, validated_data): + validated_data['space'] = self.context['request'].space + return super().create(validated_data) + + class UserNameSerializer(WritableNestedModelSerializer): username = serializers.SerializerMethodField('get_user_label') @@ -61,7 +68,7 @@ class UserPreferenceSerializer(serializers.ModelSerializer): read_only_fields = ['user'] -class StorageSerializer(serializers.ModelSerializer): +class StorageSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): class Meta: model = Storage fields = ( @@ -75,7 +82,7 @@ class StorageSerializer(serializers.ModelSerializer): } -class SyncSerializer(serializers.ModelSerializer): +class SyncSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): class Meta: model = Sync fields = ( @@ -84,7 +91,7 @@ class SyncSerializer(serializers.ModelSerializer): ) -class SyncLogSerializer(serializers.ModelSerializer): +class SyncLogSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): class Meta: model = SyncLog fields = ('id', 'sync', 'status', 'msg', 'created_at') @@ -147,7 +154,7 @@ class SupermarketCategorySerializer(UniqueFieldsMixin, WritableNestedModelSerial fields = ('id', 'name') -class SupermarketCategoryRelationSerializer(serializers.ModelSerializer): +class SupermarketCategoryRelationSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): category = SupermarketCategorySerializer() class Meta: @@ -155,7 +162,7 @@ class SupermarketCategoryRelationSerializer(serializers.ModelSerializer): fields = ('id', 'category', 'supermarket', 'order') -class SupermarketSerializer(UniqueFieldsMixin, serializers.ModelSerializer): +class SupermarketSerializer(UniqueFieldsMixin, serializers.ModelSerializer, CreateWithSpaceMixin): category_to_supermarket = SupermarketCategoryRelationSerializer(many=True, read_only=True) class Meta: @@ -255,7 +262,7 @@ class RecipeImageSerializer(WritableNestedModelSerializer): fields = ['image', ] -class RecipeImportSerializer(serializers.ModelSerializer): +class RecipeImportSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): class Meta: model = RecipeImport fields = '__all__' @@ -267,7 +274,7 @@ class CommentSerializer(serializers.ModelSerializer): fields = '__all__' -class RecipeBookSerializer(serializers.ModelSerializer): +class RecipeBookSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): class Meta: model = RecipeBook fields = '__all__' @@ -280,13 +287,14 @@ class RecipeBookEntrySerializer(serializers.ModelSerializer): fields = '__all__' -class MealTypeSerializer(serializers.ModelSerializer): +class MealTypeSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): class Meta: model = MealType - fields = '__all__' + fields = ('name', 'order', 'created_by') + read_only_fields = ('space',) -class MealPlanSerializer(serializers.ModelSerializer): +class MealPlanSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): recipe_name = serializers.ReadOnlyField(source='recipe.name') meal_type_name = serializers.ReadOnlyField(source='meal_type.name') note_markdown = serializers.SerializerMethodField('get_note_markdown') @@ -304,7 +312,7 @@ class MealPlanSerializer(serializers.ModelSerializer): ) -class ShoppingListRecipeSerializer(serializers.ModelSerializer): +class ShoppingListRecipeSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): recipe_name = serializers.ReadOnlyField(source='recipe.name') servings = CustomDecimalField() @@ -314,7 +322,7 @@ class ShoppingListRecipeSerializer(serializers.ModelSerializer): read_only_fields = ('id',) -class ShoppingListEntrySerializer(WritableNestedModelSerializer): +class ShoppingListEntrySerializer(WritableNestedModelSerializer, CreateWithSpaceMixin): food = FoodSerializer(allow_null=True) unit = UnitSerializer(allow_null=True, required=False) amount = CustomDecimalField() @@ -332,7 +340,7 @@ class ShoppingListEntryCheckedSerializer(serializers.ModelSerializer): fields = ('id', 'checked') -class ShoppingListSerializer(WritableNestedModelSerializer): +class ShoppingListSerializer(WritableNestedModelSerializer, CreateWithSpaceMixin): recipes = ShoppingListRecipeSerializer(many=True, allow_null=True) entries = ShoppingListEntrySerializer(many=True, allow_null=True) shared = UserNameSerializer(many=True) @@ -356,7 +364,7 @@ class ShoppingListAutoSyncSerializer(WritableNestedModelSerializer): read_only_fields = ('id',) -class ShareLinkSerializer(serializers.ModelSerializer): +class ShareLinkSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): class Meta: model = ShareLink fields = '__all__' @@ -365,6 +373,7 @@ class ShareLinkSerializer(serializers.ModelSerializer): class CookLogSerializer(serializers.ModelSerializer): def create(self, validated_data): # TODO make mixin validated_data['created_by'] = self.context['request'].user + validated_data['space'] = self.context['request'].space return super().create(validated_data) class Meta: @@ -373,7 +382,7 @@ class CookLogSerializer(serializers.ModelSerializer): read_only_fields = ('id', 'created_by') -class ViewLogSerializer(serializers.ModelSerializer): +class ViewLogSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): class Meta: model = ViewLog fields = '__all__' From 058723d5831ef5403ea30f471a1298d5368559c1 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Tue, 23 Feb 2021 20:54:42 +0100 Subject: [PATCH 32/96] compiled translations and added hy --- cookbook/locale/de/LC_MESSAGES/django.mo | Bin 28301 -> 35740 bytes cookbook/locale/hy/LC_MESSAGES/django.mo | Bin 0 -> 47554 bytes cookbook/locale/it/LC_MESSAGES/django.mo | Bin 29571 -> 36190 bytes recipes/settings.py | 1 + 4 files changed, 1 insertion(+) create mode 100644 cookbook/locale/hy/LC_MESSAGES/django.mo diff --git a/cookbook/locale/de/LC_MESSAGES/django.mo b/cookbook/locale/de/LC_MESSAGES/django.mo index e81bb3b7c960c292530cf4c2eb0a3096a7367a31..116dec9ae7603beef83da4bf64ed4263223f42d2 100644 GIT binary patch literal 35740 zcmbuI37nl(dH-Kf5Q7MUAPST>ktHFSI|(97NCK10BpI@rnUDrhxXXL*+|1p)@4Xo& zZC$8TTeYHg*H&$@wzc?gwMA{QTE^Dhwtua5v7)X1Yh8*}?BAtozrW|4^S<}a3?zQM z_|ETr&wJjpJm=ZYbIysMJ^S&$9PyhyDT*!xd#6XyzjOc5^OPDzGd~eUH=i0sb?|7hD-dj|bO)PX-I1 zzTXV~B)AO}eO~Y1-wUdoclhTA{QHmi^iO#FjDP<{P;`3)6#bv{EXE5w9~3iyl|S>UU|bHLvQMTh%A)%%zJ`NN>v_4lC0_g_GjcL_v&3b+`L{T?VTDYe4mT6R7XTLFL=!-%o?$ zi^HJWGY6{vyFul@$EW`)sQTaR)87rM-1mWM#|QoMr@;xHAM)v!UgOHS3RJn*gQ{mc zsPCqIdKtWy=N72(cnhd}?*^X=egHfKeg@S0tH`W=ZwL2-eNg@VYfyClh{sQZlB<6M zH4b0*=_g$mMVIk>2B`N}f$Gl~DEdr#JOGNnZv|Cu(PIZhs2C6#S4+e-27P<=qUb{1SK@IOEg*3KW0+9e5u21yK3E2WnhS+T@;3169tG zLGj%)K+)w2@M7>VsPE@N(fb}ybbSN(VememekYyL`EjQ00BgKmQOEADp(uy*~%Ml;;aU)wk6@?+4YMqoC+_ zH>i4k9aKMm%fEjcc!1~kfUCi?ZgBi@9Vq(k0#*O>K$SlOsvk$elff5&YUhhR{sQ=1 zo?i=!uKxw9obQ9;le2Dg^tcFo8qd!J*MirBYHtlh6r-cyx!@myYWIU4KLDzo9|gsa z-vULqQ&H*{fER#j&o!XN`9_aBK(%KtsCL}qpKJa(1y%oxK$Y_<|NgC@`uk4seDJ-X z%KryY<$oSjJH7;}-0yfib*pRlIiTu2A5{KJK+$on$Lm1J;|@^cdKgrF6;S0iKz;W! zpvrj(sPVf86kXrw)8FCoy`akZ2&j5K1_a>hZ?=K!d76~T+ZE~xtM@$X*;ieLT!TnGLMsQ!E&RC)gao&tUY6urI;>ibi+ zyY#a_jrVz=%DKSfrJ%-n6x8?Qpvt`o6g>`rYF7zVxhbfAya-ggUjgd7*ZK4}fvV>| zQ1!eW)b|g7r-B~?Mc+??`tIL-`qw~}{|Kn>PudYh>%mjO)!;SY%fUOq%fPRKJHd1K za~Ql0MAV}D!TZ2(fy(zglTmaz_+fAj_ziFac;QX>RN!9lO7LFr3h>jQ_~ztYPQITC zKAq>)pxU(+RJ(V8WR3QKqQkF&E5Nsa8o#%L%J;XR^u(t?jrW&9<^MKV1D~)P-UZv> zE#NPKr-2WHs_)zW`TOAMJfFJ9(dlfD7lW%wUk8fL2f-(RRZ#V`eEQG$=U)V$LHcik zsQl<%;8ox^K}0NCz1QjcBOsSpi;2>X>O zXiWNA2LBV_XTc4;e>+564SwNPbT4=YO0x%k9dp-FR&)Q6|rOLDBck z;8Vaq2A>EnfTHKeK*`D9gKE#0LD{b#_~&!WPQR@I#a9!c=<_;I^nN!ee)uGK7Whx# z+2B_|(dP&L{l*Hmf#(}Rh9r6gD7yX=xC(q`;>z0&s+~npdNl>5M_&d0JotN{`1Z=G zOWzHue+j7mJRiIbocHOU0!8nC1vh|S0nY$0VlYnu*Mcg411LVf352xKK~Qvh2Pk^H z$G`t1sD3{Ls^0H2pDi=hdLT zKLDN%RzQ{00XKs$0Z#=V1l5lZff}cO1l8|{{QEEY=Z8V{>)W8{c}m04{ZdfrH-IW{ zH>h!+0xtxM;FG`?fNJN`uC?cU3;pvLE7@Jw(GsB*6Z z3*b(lJ_oMg`K90);A=pA|3*-B{5|kY@NJ;R;V(ehm%jyn8a%VZ+y#6EI1YXYRC}KM zeAoVSz+*hG16AHzK-F^}C_4W+I1fGuiVrq*9UcHh-x*Nj_%e^L22bbtH$chR?}BRI zd%(-VkAatg-vTvm7p9Kx*MXw@Ztz3k9iaMsMbC}vvq3#?1)l=$0afnppz3S;_df-S zu0IE=pZ9>u|I6Uxz_)-Z=dGandB1;tKlmh`|Hk8Iz?D4z2dI3f_t9zK)4`{Ln?a5D z0Z?>nfZ~@fsCNAeZz82JYydG5h?gLfdyFk(VeLnpY zpz?hd6g?mIcnU%xx?TXPKWjmivl&$Wo#1!D!=U(Y`llS7?*Pxlez!rj=Y4yxP_gR%qv?9+b$KAqRJm1eX#q$Jsu}^;ncmr37v=4IW zx0&aY{d-h{@$}6+i$_P4f!~X`exK`d(!U6PjcYykHSo{4PUd=uOTSBfS-O9Z{_v|h zh`tAwc>i1Aq)!tM?&n%T`gX9*^?WY3;)i%+_)xTwA$za{UFDWH|iZ$jvWv zNnc$w&<-9W)J}B0PdmWF+@HaP>agD{`1_|^ALZI+Dfs>1A8^fbJUWS!y01*yJHTCB`u#W8opy&G2>w5RzsKV@!PjtY;k*Cu(*(cD_3K=Z z*8{&Zcprn8a-GDz;&xJcMc@luS9AYQpniYP^?$kE$8|Z^3a%&f{+GZpP`_7l{h{5_ zPoFjpZt`h8@R|PpJ01l;$#px|HC%tk_0L?-;=4D2|H?J^dp7BxB;nay7jl0p*LmEJ z`b>Lyp5Qv0EBsFJH}3_580EOi~S1s=W@+(9pv2u;B&dA{WnkLelOSH?-m};@dY6-+tk@IJ(I-Eq}Yf%jbbZqwk!Qc z5*Hhd_FQU7t$M2#x2u*XjZ5v`OgvZTPd6#oJ4qTBTa~!g?j>nq(`aYQ@oJl@H#?2_ zI87Q!xfd6GDRH&iZpJ-Y(x|6B)kf(_t4GeG^<*xoWVN-sd|T|6XDoNSmBjPy{$p0E z-p>_VR7OK9-C`}S_u^jLzON){y-VrV^-epj_v-CdAwJyh$7P67Y^3eDSgFuX_0UQv z#=Uw^6lztDTP+=GxhmB)M=(`g?j}VQ=jx@O-FZjTVqEU0J&_{RVHFqRZTi9nqScr` zZoPXo9C4lTYo}?wL~Bd)){dHrP+NQptXHM>opHV8DI!Xo&_Hf$)XTGR8zO~{)mw49 zTS>a=VY@@mRZ%7B73&R1tZ^*F(=$oehHRL=*@zssYw1k8(@`(PD9ephqmlDUmBv+y z^I^1yzJ(;mt*op*29jl8my2DP2_B+*y>>_3YPUrQeL|$0s<+A-{c^k6gn<2&@hI|# z0fTf-3=v2@)e?&CipPy$m84p4CC6G~Vnq}M;Pgbq1%eC<_nTaUucXE!u;wYNUq|&C)vPl*2#cV>w>SrrSXeICaU6f#T;G4y2#tYj}M>drye9QR6)`L4XuirFk zPtwRXy6$BmX&nu3%I#LQUh8);2vE9;cFiSsxPOwzO50jEQ#>k_<4T*F*mhuI`u1HD zhZmO#sRP?Dt=OuH$Bz_SwKiR>7W<7JAD~`fuc02LJ(#@Mt;Dm*u$Jv~+ehmfP~!-3 zZ@oq4M#FVxZl;c9hYdRY61)U;XIt$#v%BO=$_)3)cz+`i>p;n&Iv=fTKQ1ACe-C(f zhsNOYRU)nTU+>(#>wi$*ZX|!wUa5X<#+0G^brqQ7yI^nNGCXQ=gyHB|i!c2S-aJw`1VZ&cge zCaI`;*_-6fUd-^-8}oTLO!o1;>>H=kmh_-A-qu&0sAO{FdSi)o5dMfbwE z({0rBrqR+C^i9$r4Nk{VmG6vdCU-u(mJ4Y`%uRs>UB76&k)swqewu1jN=dmWH^|JC z%61A>s-;<+P2#crlX!K{?5tbmkBx1QpYRK-pi4z z<1=n5bw~4g3iiBFZ+cfH^Oq~drt!17je+UL#c~-5h7U|}*%#`2Sv?r!_~nRMZEH5A z>Lm+i^4^2pZ^TjNO+%!zg`yi7aNg>%|x zSO$!{$dTeDYdZz_sup}%fa=BqAFqILfqfD4Jw!0XcLcB+&w^Xl%Sx1L) z!a3-7lz}GJQ{>e4p^4O`szTi6EWaC^nRXjl#H%hu61=TlLIDXyaz8$( z_bkOULp0{ZBVfF(-9ozMprp|l6X*%eaqVtzzt^>CwmnVtl8)UJ<7c62_A|AbkF&z~ z(Ac2Qx1p;Lid6E6NkBSeay+^3z3oHbw7z%HGD9q-MRv-=jsQW0iQy z!V1wC#qLVxtr~kUg@-txmD(Nkh){{-#4CNHWYX;P=Al+oIwBe)t9U16yy*bqsi!dK zF&R|9r0)>K0m;7MNBq=ec+p3LRaG$Th=6E#>1qoptVuUYTVJ}mU6SEhlbW_3u6D45 zv|dA$`@I{Yt$6B~`pe=2C}DIH2|awZ31)fz)+T)0&>gilW9?pBns=QBlPcma8f8j# zO$hHmqtxr4O5w4x2WQM_LZ`9xMWbDweSY7f9~v*S5J9I$Te0b~v#7bv_M&aYM!Q>2 zQf^EiIWEY&U}@^ujmb)~bW81-d16)Q)@U2k&d7Os=sDN)Z4D$e+SaB_X%`K!A`z|P z(R$6fB&A}v5bs6oB_?HM#BO9$Bqj1uGr^i3A>tG(0;L3vH4U(N7maq9)#@H;lAnPj z@zi{)>>j&KklEYrcFk@|JY+WrSFhjUu`?e}BP_W435;Zu@v=J7nIE0FQyQFm88RuX zjC)aFVmTRPKVOv7fxhL1d6_6ogiKB>u|vj*s7jp=3Xz4)DBs1~ruvo@nq%#gcK(R;mLHV`vmJ-C)S6i(wvP9X}McBS zRlF+pDvQT*8*doi4bmEt=&64>Z-YCI``u_4E3wlEk!b+^8E9Z?slF(8&zK`N3I#Yv=hZf zr4G_)r~G`xamFVTmX-SVE?6*n2!M?_>|J)kC=;48arX8YNhZ+KZ4uMSmKF-pq`dGH zqq7??EalNugacznf9nNd=qY5E2J~N=G9)Bn#(kYB854KuPxOX-UK&@K#}lI)P(>{; zzfy8KREdU-H4FcqC*|l`j9_I*>{1S{i-x!u7mn3CCXI!7yk0SnpzIti)n0Dn5VIgs zcYZGXfTS2>nEElF@djV6xX867bn%4wYO+;s^cgP~D;bGzjh`DLKnR+xy@(k#K}T5n zsZ=g6!t50Ft4V#BP~vbJN9d2{`1nR7Wb+j6o!e_(;H2bF8Yydf>!|#5jVw8{dmELb z%+~OmQPh4wq~@V(o-K{MlNK|K7PWm90s2;z8ClzT$B#>ICBVq=V~*4ErI zBU%A^!wl3!Srw)!Wv%_0In0>PyJjjFFNJ>3tDo?llhoaaEDdDP_Y+sE-)Z-71u3q1 zwm3!07?FO<9+*x}niqjf>?BX?gtP`%!osC)hD56%U_xcimzJEYl;a%X?8NeVprPG6 z-X2Oqd?--7=hXvEYGa%Amu^J6`u`p&^hT)~rGXVF zO@#|&Z-^{(bU<8eg4|#VwUYNOiS?Y^cQS2nH_*E&$v(ulqmM?K6kT|C+*6hP>%$L=qP_iQiAJCf#*6dmz$446^3IvJOOIsB_(VAoM6JF0>B(G@7|XV+ zRRZ_Mxqbz~tqczqIpEH9Eo@HFA^1hNv!=ND(qLlAHqo^<;yLZBRwd2R zzS(FW(+nE{-5A;TXbh~I_ zx|6g8w%%l)JJa5%_p~djgaJb1H`^smQ8jI`=o!l&Xe-pDML$>^))Jeox{#kCciPBR zYm;!XvD=lR8$w4@+Q8zxO77hrpzOve&5&$Q&^zoD3L={&7}c^R2saf__Bp=PG}CVL zDXl%u$XT#E_>yS?N>&3ylbq;j7Xn1LooUVwn^NeMQ)hM!wd{fSN6*xfW!L6>G45@oo@D?`23Hx?TUXmJ^Q_r=dyMof6Gn7utXIiB77 z=;Bmwo}kf?o{#k1l*Jms1l{UIpq#P`U zezj`^wy40G?uJb|$<2n0vW|%6+AUkMFR+4J5GEd0n0%jn@lA0R_c_`L3+sr0K5*0J ze7k_3PS}{56DdDpWmwX);h>qdcCUwyGR4cN?blZxND zGPs5%v6bZ0XQzZZ-eDrR!LY%R;>uR;CmX+^vJ~Hr=aXK@HiyEXJ4{Bzxr%W)rA?`} zO=P7nZYZB4voe}<=SaP5PO~~$#^8ziaJaspNpe?v5;3hW&IOlg9cB^N)8_f+Mbe$j zg?2R(OhGwewdVml<_R4{iJkMA-CUD6a%+^@ z@=dr3nrUS#--E!N8Eb7ib_*hf=pf?CuAekA$5wx0OrSk^T1SWAIgOr;Yj}{!%ifs% zW6jV4E~BNQ;x22v3bxt7;8%!4fiIoId&tNA{ZJm#Y_!groFcSZby9+xt!jE29fn^d z_qmhcZN$p#m2@d&W22-RAZ5p>Fh&Xzd9^2dLMmb)ZI^%Q%UYMaSmu#9!=Z8|iniiF zI7dy9U|W_jWtL8~MR2#{Gf1&{YMu$`hNy`e3nkcEuHLqt-t;W*Wk%sNKUdHBhsMKY z9j(d_IlTT;_$m}mi_9`DDZ-lv-(2}b^;X^{eP%}r2$)9(Il*d z#hqNR3BzDhUjk68w&+Ww)$O1gBFvB5h~aTv*7&pY@VvgdsRuZ}-#42eBc2{&K(DP&hJK8M)b+%1%jxWb@3I}BrHl?^t7=CRK?Xvj1~R^cx4o5R(w4pMR9{%RG)7-PX^jDq8K=t*n~ znON^FI?`xF-RMCjvKA>u1g9Uf+@}&_)>W3J4%A(^A5|*?>r;)8=LGA28c*Y6pjnqK zlQ&84SRgh#09k8q+Hi)t=lEKVHN`MZhR(C?4r_mGFP~MXWkR~gIT8{`#W|10!o7_B z%)-5WPAbFa7<5<%!3*zGg za-mnDXCHUm`KGjvLg zR$=v8vSNF`H7oys&Py9Dt;UR>RYR7l&&|FGne9hyGKy1DW_!j)*n8AxyRvnUy-D)5 zXBO@+&!ikBnel_EVfW31zzg^H>a|{B#T2HCr5}@#fwB;PcJz7a?)z;XOAZ#9;O`nd zMU)b;N$Ng-Vc@J0v@rSOtR;O?I1EzGIv#uU12_~^z`&RBmV zV<{0Y5+#7a`=*`A0CTL2x5EB*r0AHV>0|b-8=nyIpjgl>OU@8EmW2>dm)&%5x0VE_ zEK)R*F*>xNfzRoqkaZ{w31g3$QAkXIs?RFO<}bl>ddxMB>k$jHTk*mJ zk`U7*3ontpJ0(2WgdeTiY-xoB6^4HBppn+yY?>xf74yV!csHq+IA{cM!sshztk>qp zxapjDC}>=bt`{d}c4%7ZBLbst1`!2@ z(%zV*?`l!P>1?Dr?O63Fhm659JuON5fUd6jq{cwQ0zmmh@b)4!SEYfLO7u zRBi<3&y|G+oABHfVQun(U(_YG%qWUc7kWfG(!s7Eo7*_M^TrP^% z+_VXys7RhMy~5zg&IgBcoogs7Mr!m}I9Q|#Y)woYjdylSzt-ivvMjaNi{5K6nhfX` z8OPLyuMb_Ft4TMF@7*W90hE-=mv_qW7^1}%54AzQ*&6v;>M-rL#9R8TEAYTa^1KnU zzTADs=N$hF<=ELJxh~mQrJ|tvKImvor0NN8da>0UinqG*s>L!r+l#gZ}x-tqNkk@jMp72k7hH!_AZNY=UR6jE@+eAGQx98MnbhfENNQ80yp2V8;9 z1?w$5fZu8pB=nJ!6&6enX<+FT`bxRIpP?Te(7giRT0$NG{hDZ3sH zqvlbfq1%%?Vw-Uhi!jgdd|;=2wkP;4-DsDxZ?!@9hY~U|@QrLF3^WGQ94=pn$YXwU z_|m%4isu&Yl{d8H_|M3YqSEmnLI+HU!m*!#ntzwDRAw+D2G{0vHnGv9j}P`z18l9{ z4<<|LV~K~-wzFAMgYE@o=-pU9ttHl43gY8Nu{O7GKc#jh{BcuwYutE9aG1sHMqYX09Q+1wqSP z?u7^FfT<&tKZkiZ+jF92K^3nePN1}*Rz2qVBiM4`el$pC$fZ1Phz_wWB6JeHjDM`T zsI+uyk@wcXsiZ^9kfgAkvV!rVJ;v!_(xsGL=rhhH)svB>@0?0m=Eah%C`1C}Y)CU> zkRM_4GkepLLn=&LGBwK?Xv$-k!Qzgo+C`<@!ipF?W$a>xDi{$!69 zMYMI{0dYyRRcsM2$9vvP$h}8d6Ke7t6eiuKoNSgNw)N9gcB0w5oce3MXnPm#N>P^O zS;%cio?6i@VX_xEPo^|!prK;z&LgI z;<_cX=4zD}_55y_+*t;8Pq2hzr$$n@lp&hB02TuPf$qiaqQSfHIxvew{Hk_eLSbY# zBU85ZWmmhS2E;eF$;U@TUv0PDF*4elmOndX&5YQ)CQj&bT3ULCxfU@5PvOOaraqfh z!g}Dh5HG{xr)CA3oQz>HlPERq3l4~4Kpcw+J+Tv%P}KtQBSAsu?;VQ-4?=1m&FUh8 zUQkI3pXDjOfS!0T%KXA;V4fR=*`QZ+n!fz6(! z*kydOgni))fF&KI!?hSswCX-p;}+NA6J7 z^^wW(a7JsQ%Rho84Y^zK%M_xa4ID>$k6J4cS%}sJ)!lm<6RfQT&1bqC(Hxwu4WHd| z?qa&!*)4xa2i|ehd@+2rH}t@}pdeEp3~;$n@>21<$GJ0owXYQC3eQC<1Fst+xLJca z^o+L6JhF+pi)C|Sw{9-b@BuG3IBuyv$cJb4%(Kq;Ukepl!gn8;tF}u?;&5 zW*kz8cPgSLpN(PesxhLm-*Unl6pL0)L@lJ2O%*b?_XgiQdMsR;EVlEwrO_r#2NygA6>vhP8zU*s97uStutZ3@9|!d>EB5lsz@)0oKqS zkRdL?jIwf$^S(o~L7K%$T%^-4ePz#Dkuc7VAQwRlf0oP~_b}B$o5g#HcGwBBc&yVI z$-)*8$@C!SG9UGG8@2rVDRx-H7t*4tTu#*SPnDU|Hn=J>xX84|Ri0Nd)OxEv^edb3 zWg5JIcc$e4c9eM=qPe;Wk6)#;+5T>3pTR>dvNVX{G!E&;_Ib2hL+Q8128TeRPco9O zxA_8?3{K!Hzo$d`*b4v)l?q$R62S69e)2lDT&bX=%r4}DSrn-~18)s#Q?=_@pKil5 zI1h3f-QQNHyKrwfSZ1x_RW?^koeuJ$D5A^ZS`Y!Gu+6EM8CDLEMpRuE;*ehYa)W38s9 zq1=@G%^qx%UkVyB4Fi6h^Q3Z*ZHb%h7Bg_d-J;zL|J;bSN;>mB|ceAkrB&RcA8gLdC@Mf{MtJ^5}Im;TQmaZ4UC(S@p?sg(XhuZuBn`Zj@5i z8M!-}2blRsVY9IfwM_HY5$);D9!prdrh5Z>hCjCy8z^7`dbYXi8{gNd>t)i z+7f?(V`Y6^P+_a4Cc3rYh$1@n6dN!2JdV9wI>RfEd?1r^bYy33?Fx!Zr&=BPV(QSx zkM@PaT?F5e8#9Tv$fd*3Kmg_AL3+V!E-1v4v$Y zxjZDv^Q|JA#$(BH6|4%^8ShK>y(^bj=G|um9ETOI3QP7i`Tknn@s`~7RfI-SkDDvg z(SdgEmzL2QI&av4XMBiZ2sY0!alZ(~|Fbc1HMVVuU?&VekhZ(&I1n-n#XTr7x= z3bsgOq6$ZGqJPjQAL@yesT&(xl2enZc_7B-qMNN~N79za(@3X#$Dm1Vi!)ZVMXXs>sWB?^2n|KhX-WMyyp@z>vy;Ec+?Pl zkKqK{=(;2k#&gF+RHL1lBWB2fm99BeUQiua&|%5#$j)NF(}RPtfBq%TdhS#*KrT7F zCU~a9b0bXLj`7bmvC{y~^q;n*U52xBKtiV1dtGwC+|fA&#l;-09#k6UYz1t6qMrzQ zlVx#Mw76Ul8$1fg=8yRu8?#ZKX7*fU*0qRj;IgNjcyV!I-%y{tCI3gB1|-?$Yb zTzl;+h=@k}$T?$#@JSzs1m8{1C0VNWpEn`fP+l*QAq-E{#J0=~lr~V4R|dHv7-y%2 zPS7j#z$e}ym@?CuW?U~#O<_^_QA>~CnUCUTMcNjj`F1N6+t@KY7Cg03t^lZ8D97Q~ z{7`-w5(pnSl372Ux zHd>GR4j~N@JKG=x2WC3UIF|JiZNxxo7w^nsQ>Nwwcrxfdt zX!>1B#I$Fp$kNuO5cxsK48V>qxhkJBufCIcPdPPn&~8`D|lyOwK=ShngNrU@l`Dje_D0;*e>e z?8XIW7d`r5r+Y^ud;m;Qq;T(py2J5r{>9?_v>x-=jGvt*y~$>-i&AxFZ&8FgU)In| z*f$*LBOsp5&%N&)1s@ts*TsjWRM0#ULBNLjZl$#c>cAet(b6ZpWbr-d_ptky7<eO>Mo zoh(v)exCyKSUQ)?uwcGg{Mb)N29EeGTdAoWzds9c&^odRV;yiqsGWD+_-02Gl+&ZM zUQOYxi=+e!c=H-ogDk$1)5i^NaC}6qMVlRsPNryB*U(zIEpsdKW+4W#f_JvPy$dQW zxRC|CR&9$IF!E;A%#(A5mH4>XC%DdUE6V~;ZW+e0mEumpcht1Tt*Mptk7)ULuhzga z&4LPH({r(8Hi3;Y12O1{uomK@890;SxZhRW+Q1AHwf`G>4g&Mt{x)hK=~%9cDzmFs>9gXxoZwkbUPp zUh_+|J=sQvPZR_qa%UefGt(9@*^?@9_9cl3by`1a$<8{fsR}ZCHKS-1XMoP zY6SF=>6EF)r9jKb-J;{BhnNN|+^Zd#*6HOJyo_yahm3__!#oE~)lA(!&6ds)jyPtJ zG1bJ_&7b(z)br4s&*wnjWp}u)=2H%(EnOBkh}IpRK1rAu52mp0tRR+lZ18;Hi2GNE zJk?RbF31(Hviz$o(g6*FK4w^0M`hWuv61P7k&2zGTCNTe6guWu2GTogyV85GkG5S~ z6Gu9l&jpvxsh8iy9r;s*c(W0Xz5IdvPP}L96rRP{j&GhnM*@3VE$7hR(z|%I;vPwh z!-d-EZ-)zmHP5o!go`J0`op?bD-5rN2ypt4@%(_Hv&8m_y&{S&F!27ELNpH7iK7Vs zuq&-Ff3Os5ad(?^BveLd<7cJTN|XYSrbozUD<_M-It3Olv15wOX~{g*46l z0vb(pCXDiu(F?jHU9??y*|EyE!JB$G-p+pPQa|gTRE{Pq;^M%EST)Twihh+YEIy~% zCNyomMW*ha$99NucemNbN|W@2fM zA*M(>shsfC61MGXl@%tm9q&yJo+Gz-eJC~DS(`VEXgXaC`_lMFHN~Q?u7M?tl6kq- z2`kE#u%pXAST0wV&0b!LE$Hkzm>VS59%qs8P0hK%)8drBEqKDmw1>s&;S-Ue+3st~ zBzWa_%??LR^U;g(EeO}RH5*(0&?d2*0?QR8m)m0WNR1yEbL?ONuYORSxbQeNwx=W* zd-EJ=cbjQw{^qcC~Cl~Q4`pNsdzm$!(FK7?#4^;eymUbR{cI+h32RRI-7iN ztWSQpDIaH?Z0_fymU0p1VFlL1M==eLn)|PyX8ay%qTeFBY&Go5`ZplahJ*?_VJ`MT zH55kn$XbS)(N(ApccPBR?WlT>pk{akwSv!KLwpH zzbaftf%bYKY5-SYBiw>|V23H+gX;JmQ+@>1@Dr#Nc+TWs$4TVhGv)o#y>>>S+8vMT zXIg@U9=y!lD94fHqo|qRi>i18wdBv5@^>(w{5PlxOdQ~C%~a!DY(lvowGtsyp1@w@ zx0?Hj{UkJlqo^f0Wqbj3TF+u*e9QPZyomgFSdGInyw~eK)Qmqu4Jc!vWo^cxsQjN$ z?Hoh3`z+4a`~Q-;F>sJ~c*bBmD$GDtbWmGRVe%1FL(8!_Zon>hJ?gmws1-K)Zwf*Sohig79`YBXVgmcKvhUL`QfM;j6-d~1gwLXqE>7^s=j0LVbmTkH~ID0 zll<>c1KMx$$FQ~D{|`v0gC9^c`UN$E=0m&>OlRyvekr!Zn@}Czi)!#7rr=3TZlUo7 z)JmPjR`@>ZOni@;aNVJ-e|r**N%Y6=sMl;JYCw*032FdgY=JkTR$?FWb6_1ob^I!7 ztIioeK@H$5RL4J=e4|V+-!7B&*G#)ppoWH^9+-jJipx=7vLaLmt55^jfNF4u@pjaJ zA3!~S05y)W8ad z^I;-ig350k;VtntRD0K>%5OytXdi0gk0eNF08gSmKrdr*WTt{X2HNZ9n2r~q_AVEb z12Oq|s1;a%s$XObVjJ?yP|s~et?ad^2_|-t&;a(Kmh=#6#HUarJdJwrT~r4jp*r{s z_1t%;rEW0FJ7mpK^}C_U`=Ht#hJ^O#|2}(Pql*=kY9lsfQuU7jd-!%|GgwM(~nV0`aNnZ z>hPIU#je;Id!zPl466QAEW=B&2OdN1@%yNbJ~#PqP%HW)Y9$&lD`sxB#TI)1$C1#U z%tSRjPdBjC7F29lebj&=;r%e?hg=qQHBu8@3`p098KTl+Q+fjXeCRwkb&O*C6Y!?ndZPg6az?Wb>jG@|FW%Aol1KxqDdjEe< zLNmI@RH!leL#UNFfnD$gY=d8#^17Tnbuqi)QBHL&G00uftOIH_f=HAw^0NB68R=sDVOqJL70tv zOs%8HC&Bs=Q!$6{`*NIo8SAfxj!~ciJc(M;Gq?g@$F_J0pEVi8&bSUWgWHUMM9uVJ z)QTNPZNVArh3}%areUGiPcPJjh842@n&AWr^uP?%2n$Vx#i$vEP&2<0Reuv|0N0}G z@5ba|Mg48KA64%ls-xp3|2(RnSB)PgNOYy(@2HCH_-b^=9(VyxL9I{`>I{^lX1W4- z#M+3N_zvn!wBzHUf%Qe@hoU~|xv1x+q6RP*wc?2)5?b1&sF`j?ZNUwwQ@a=Y;}O)r zK0(d6*+S3O*oS-?s>5v5TQUbP!~p8;+K3w1HdOmJA}f@zZt)VMSfkb-dK%SD{vPJ0}1B-$6nnyaV;%y{NtW zGipXpp*nmGwMFMl`B%o&#ooZ%qn_)F`r9xQ)$vF_<>Yfv&rdJ%22hBN6BPJK=tiY+ z6>8>JqXu*%cEEk6{3PmZoHqH-a4h*BQ8OD=?5$vyaT;m@^H3|i2-WUVOuql?NN5GF zGww#6g*%N0P)mFgwKXrIw&V@eS@&au>YEA zB?YN?1?n`f#U6MNhu~|Njm;eIZ^V2Ikl%${u}-P?x8QahO8zk%g`Z&-_Ac{&Rm;#O z{{(i!56W2oo+KKUdjlAVb;)O9K8{9>d@E{i_hMJvhuYg`P>1XcYDGRqEpc5&SBUMg zFGf+%-;53LZj*l~K|(8V7#rdw-BTmCq@?Ehv_Cg)P z8K{AmqXrg1AD$s})g$gFwkgBao}1aoj_T5w`2XgT|MKb?pT$EaEfx_Y2+g!L4g3!d z$L*+9>O(q{(Dj{%bsNqgG)t|Nwnx_p>S^zFZB+lONbDmTng(=Z1F@GFPaGz6-9z-G z&bP@NhZ5sNN6N0i!Nm7OC)3W4q^k*zMDlOJzo9OjuLyCqGMYcXipfjM{V)+F*p=k< z2mW10G^bIHg7q}<1@RJb3sFVry4l0J68oD0sA!TYe;oB@=<4i|{8#;3D^0;oMt!Z? znnniyrm^SE{c)7lkRFZ4a29b5@h@U1W!GY}-#j;s{Hw$c;v_MdXu|yqeP;hhQZR&q z5OQ#>Frn)M;vmsc8FTG6?m- zy!L8Bq6ZJxUeA!w$E5a}Z4wQQmthw5A2j)+*q-2Hn7sbWILEjPKOu$@;}bl1iMb)V z62pn#5xla=s{{W|CmIngsGp8M5WPqjqOMyB{pjfGNBm5@NyG?U{Ayc`xzAhuzpg}o z-5|P{hwmo+B=KjWIiah*x%V0Abka=;oAee!*GI&=#A#)?{zUwf$Ri#hej#2V{z9B1 zW)jJdMD6?kG5L##ZZv#7ZX%iyUlMDHCy0eaZ|>{*J@GbiF)@I$zvDy1=Y+0{D0>fA z5G{zy30-LfJD&XHEB~o-sZ?G}<{hFJkwq*g&Jr&ZUlUIe!>D%wrr|)M_Ikr4df<)3 zf1CU$>fC42%kYoHb0&Y4F*%wHGA{AHDO_rN6dTaUAmRqn8JLP)h?b;BV_$q7^+_H; z=xRmTH#ib?rC>XvgUQ#$Hk3~w5-+F**P7(N{4rv@fJ*gA7ZA4-FA}9hTcW#y`yZmN zT;d-@C*lF352645FT&cZ0g16hW^DoP)NTwi1qbj1F@^_EVK(Zzix@&2AzBhs35OU+ z+(GDC?O}B_&$KrA&G;Ch|I)xOHXwBD?A4#dHKW&@O{W5QiJ92uZ zdu;mtntC&D@VVP(^{H7lYqc+ZnZL*hIfJ?Eu_iraXy*8`aJVe!RQdzKjN)+RxO98S zpdo|Yx&;MI^8BH)xWCL9ZI?Liyn;gaXu+tO=X$)KQg@|O6?5Ew6?RFpvqRNRs3aaL z%djUp5xXE9j}$xhgqlI~Q++KdZ~~!He{ngfInMH!o4sJW`{IIgDgL4iJf?0BV}oj=v~he{*#7_wK!?MfbV*DqRApJB&iD`RfT;w5h7;tY4s;*K?sEgt1_ zzw!5KX;=6|A@yQU4#cL!i)^=l(QfxtMsxS)qW(3LitG65MFZ;JEiCEm=51)u#jbWD zC3F!D2ZNAheWni?qXxho^(Gi>)6rG3zu2b!o}r9@#6CH z3A@0F#jD&20wqcHxPCo4~%HdI$4uKu@a}af@E|6t+>sW^!4Sq zBbV4I_8j-JC1XeWD`J6V0Vl%XnAYX-m_J7H*U}7Yo>LTc0xF$5J5Q4@b66y|O~u4c z;fk)-q~%rNNX(#yIC0*V9k1wE-SWltZoewqm+oF%wT&6S zQZ>d+Uz*;*=7r$^M{S)CKl^M~o;X+*WNdD1X;zAz?;cpXJ&_*?$HEnyC2t{gCfJw% zD4i4t1;b@J*c|lQ;rT-=<57p&*7@63c0B4;w5GEuyb94M_fPC$By2$>P#R0V7nCK> zgTcC>`SHuf~Af%-5;qa30H^gsiD%al^^tnZ0|-gnH|!R zk0r~k=}t+&&jF4s<2ccJ)L&WYgi22wF6SUx)5D=aj8$A2d)mD;J|uMxLvyc-_jM1) z$GAVlhfOSDsb&@}aVlbtHRHsc9(Gk&o9LUn)luj6|+za$*-HeN4_eYrb)dBrq)ia%ZzOCEo-(RNNCSW=tz&V)l& z-&k7<5U;Wes+^U9(m+LW`)jMtaKBhSxbykJI<^yvl{%3SgJeMLRZhIjowQzb0$W<<#{x%-2g8X1s1_)vTJ6tD5=RnXx&VM}tFRH%qYqJd@qZIF#9zN(RuaB z?cZI_Jmeo^#taQOLA^pBi>{RrKSqW)u|=;8ySr~+>1`g5;} zqNl*o<4^a)Y)b8zFdD7pxI|A}7i2PZ|*hq!)xMif1d_ttbo(YfGd zAWcPgfG+~?2lf1m;B&!mf`@~9!u_9tFW~xD;DO-&ol$fo_c@M*mEZ@${hxpu$G?DT=V?&mJNo1(dNw#6JOu0j_5M8Y zb>Ko!^!a#rz7bSC4}|NT;rZ9X{ci{SUU>c!P;~nhDEc3K3j6|(0!5E9coaAQ>iMf~YS7PXaZ*d7$dO5PUIsNw^*WRsIT4 z<9;W27!-jc!F$5}D;SKPUk6H_KLo1Wr$M#56%>6Q49|Cl>o0>E z=Qly|>D%D5z@LJm)|2T*cw;Cz36ICvb_F9+4$IpKN*sQ#=2MZar7wewL> zRNspM&b>l>y%kzKQD(f}-m$ zLDlm+P;zqU*-npFfJbtDEO-)l7O4LAfv94%4txoCH>iGpA>b3B`uTNG^7v~|bUOf} zel&PAsQ#P|iqB^UJP%ZVmVxTW>%(9qfbh!UOz+Ir~`5LHp_JH!={{X7rKV9hee+kCi{{yJ|@nYx8bWrVdg1UbesCpKG zqR&cD{VIX40PCRIyE#1n7$|wU3!DKy2x>e(0#)BXfzJW|4HUhe2KD}P&h`6;g5viP zpz1j~;Blb%+zIOaMWE`v02Dn|g6dZnsCpZq#<3n$zuyb$y^n?a8$h*l52$wT2lf6= z@Br`|py<0B)O-IJ?*9T*{l5bB{(k30(Jb%)a2j|z_#W^r;PK$k!Slhx`Ex1wMi5nt zwuAS8zXnzA_9ant0{A329sD%CpyX!%3thio48D}>X`uRb z4yb;g2U0Xz3W^RN0S^N21jWDmL6!R!C_AwS6u*B4s{GSnANbshkX^6_z8<^Mo)z6--Fk1{f6b<&mV#s=UFSF2on@t3PSSeqoBt1_u$#!1+S$H z_#UtWd;;7b{0*q_{We_x9z2fg{Z=~tPXI-SGeObs9Pm!`>SFLQ2>tt2w9EC*H**jC zugj<#TvZ|#0*~%S)@bOK9&{e;qEmmx{U<6>^eERKUF&pQQzb^C{w`2@@a&q~sh5I> zaQ$jfd|d>}ZY~F>fMu`~ybhFIdl=OCz75_C?my&m_dyU>7Cj1z?oWfS1P_0!^ZgX? zja91&xu#K9-RfoT(1FDejPXqyazlM`~gUpqW#CbUsr&qbA25sdD{i5 z{_lfRRqkzG?l@5GoC>PG#o>A#cq!M{f$H~xaOj!QX&i1P^X71s)DQ1ghU( z1!$CxDwl(f3>6>%gCZYJcIooG#tqkz9|0qSyPt1Hiukj|De?djCrx zU5TCozYlg_7e%l>T5vry0v`kQ{%dY<`dk412iFZye5t1Vuf(LMYDk%9qE8wNzT&_pKMc{+s`nTXQT%UHM(|rwi%6`PF zpyYPPP2SI+fTGtS?{j_~3yRN+LG|-uQ2eieDtASAek1rQu0IK?Uw;X{5PTAR3HZ05 z)(Q+?;#)bc;t9c_00kg2QLC20p9|u{g>Y2dN~i&_2r<(cN2IV zcq=#$d=#7s{uaC#JmFT?r#}Y|MyWkPv z&%i0*ejoOBj|FwTB;Z=`6s~UsPX#{@s=vPhrN1xxi2LPNgQ|BV;JZNe`@`Vz;FmzX z_w(@l(2u&@OaTw({@I|OF9nYT-x{uO0AI@WJ)q?D39u9VYf$g){}W;cmvH@Hc>W~#zWtCJ@F?!D|G2;RQSiIm-vx@lAN{1$X*(!={syRV{vure z9#nhBe9FhW2%ODz9n}4ep!o14D7pC!*aIH(X&>j+;ETBa7$|<;15N|CgRcai0*?Xz z0P6WM8+=?RfEv$2@HFsJQ1rMN6rDZ+if)@h>BScU{t#6Ee-BOtUwE6xM<;`#!|9;L zy#iE!2fnHCBNr`3&3}Qhwq2I0rmd(HlmZ@ zft#os`~dh)aM~T%Kgw+e&*pl@X2(IWi|egmH~6B@xZNHBOI&x}<#z4;pyc#hpy>ac zEiR`gfwC{>f*Qvf@EWie6upSP;__-oC5v~JQh57o4-FR;KkrF?!P@;e+_&w*S`cs{{!wNHU&GtxnMu2 z`;c~$9=ulf zlS1GHp^S3k*K>_nn%=z&6hHO3l;hiWhTMYR3Fqg8cfZCpWQ$gDy%>CDxc@Rxa|g-o zS2*;U$Myc<`P;cZlSA{0mx7|7KI=IU>*xgT{{;L6$1KkKz|V5*&+!z8KF5W+bpDwB z@ac7k{uAut`6t08;huQ6g5x0Wp9_k&Z{^Sj5sseA{r?5NjN>E@@%$W)^En>p_#j8} z`7|fe-Gez^k?RMS(K|TK3inoWzMA6#j`KKVUy{#>l({KfEDh!VEL@+-^_`p_!?BKI zHrI%s>3=8Zn>c?xcqE5Dh<5Y@M+e7&+j5yeO3YSI)o7@dJ*tIDX18 z{xhE&f639uJFnxATw~3plRU4L}IM#AJ zi$kCHbG(P+6&$ErbYZBQQ~P`*;2iEhkMlFYnW4-)uK$hW4IJlkua{#E=lc8~hv+Q< zUkI)Y@9EYH!}+0{k8wPY>!-n!!MA~b!?BIyxg7t<(a-&3IDW{vJ{LRKy!;N%r||68 z;I$kT&Tk0MXM@k@`i&gF*Ks%v4aHH5~FW-Q2?*Mi+AE^BayU?2LRJ_`k#X(t!UCet=^> z@BQC!Pw-)mk8(U)7kpm8^B6piV?WNH#UZ0t0{(&HG|vAP)Thbu*BqbYIDz9Jjzf5U z3%CH(=SGgZ?Tm4TdyBxi;odNKY&idIK*8%cF5@_zXQ? z&GB;158yb0^UhFc8P|(B4&z8Z&j}~Hz(pKdo17k=AI0@4;dwpatH3w${8Qi;I7*yf z2mTYs?>KgFtl-|M9B<~(=YEc7bN*Gk@|fvEoWF#lpJNTrc7ku>SRLMZG3U!T@}Jjp zad^1#D0nYNgX2dWOL%VtoB{3uj|JZd9?kJD9Qu^G_k8d+yTVR$tXmg zaDE9mooAotcpt~5;r=%`Ul`6gjSkM8pUm}Ku21Lq56*w30(=HJDjZum&JX1;=lshY zQ#g*`-q9RqaIVkUq0GlPzsl|)li}VsxxR?w4P4&`9?0>M@GLqg-pgn1(EQc?<#@1M z8iaDO~n;ZMEXT^TAj;!?FIuGWUj zjgGmUL-QwVZB=D(XkaXEln2V)!*MCp68F|?gYhsu8K^Xd)f%;ztHYFBS1FH{d(zfw zb>1!2yZfzlty+%9Y9o7XRHGj)RcVZl_S8##ab-9juG#xNH^e9nG-`3Fr-y!OgjPc-969g01}Ij9r5b^a@|-~q;JZR zNr%?xuMG`p6cUtnoEjL&WTltR^_0dEZWrE#B$GDQtuZDfOW*D;)e$CSh~W*_h9s?a zT7uB~M7mX#YPY!GT^k&PfFlj~QQ{8_gLJNjD5S3X%2ZvKj2ppv%Dt6pdD4DUW4&Q7 znc!1tqrc>IuY3Kb!7xl6Z6JG8XY=MTzm%0^}ce?-bK0SR#x{TyO7O>iwTt|V_V|-NY&hj ziCZaNQELqM)gebuX}HuSk?$&XuPs-5WEgmbf3>x7*T}HHT$Y0H6zjoI#pwdUdNGM3 zs;!1ij7MwrwLV^qUa^&&WKZ7h#;~ZAbQ~GzDR+(Z$uE|(UJlX(adGlt??X)XdWaF+s>?l{)B~Q9*)!s_qNF9d& zrF*findTP9Cw=UxSr7Y5>tu4gwpEK4u3WtOvI`eqI=)UworryF!`4*1=<-svuf`C2 zOCtlrynuN@yb2>~3?t;FdQZHzT(q)7_1e0M7-|wB>8(^LJTTyc8SSs&*%5=GkuGEj z>aMNUM$PY1uG|f~r^G7;$`TzYS!i>jq5ZLh4C7rH!W}wCWMKZSfpx%;_twkwrq(+= zDjS>Af{u8}u$k>H3e`qX!&)`%^4wC~UoZF0o7z7-Jk*%e+1ZB$8|msm<~!Gwy2{n^ zY(AYK%9=X=yvp$TBVBVlOY<{sFYJdE<$+pXqu9(dtD82AqK&EZ<(;!8GGSU;s;}*- zjhbE$RQmddN6Y#f4|0EGC?;m;8!7c+>ihAFikuiRX31ouw^kqIE~Z}orhLV44Erhr zW7#lF_ldpi9k*#MBN!SR?yps6szG(6BT%bS>zo=7m#|mE^QK=wwk6@aH zU2MaMjmK&AEki&daI?JxoLvZfN3}fMi8@?P9Ng$kD(-BIQRx+}V=8h+o^Ju%s3I*x z17#>DqnWo#jgj8oN_R!RZsNYeCc=DYM8@pZXyx3l`726|21XUzi{P%VVW#JHcFo7$ zln1znq!XwrcE&VQI%BVuLR(RDGhm6WAIER>s7j3AXoxFaXimDX>ZDdBsype7AiUpcQN%7#JfY8Lh?BXmAkXPLD^b724#Iw;{IpNf#`L_7GmK9ql4G9f2)5=Pq(I zh!QfgV~otRLn_*6TeDa_G6ct5+zdPnCmVeDQMgx#cdYEd;31{ffEzfu55t zZ{U|Sgi3e4Cic^Nw*qolQWgxk!mxdq%1F{NCd?XZb(~E{yi~5YtJ0UuI)>mA!NJIo z3ed$$1APqvrA!LV$wTMrko=?)qWUNLC{m@u>e_uOjR>L6UCaW;;{Fh?#268*elNOG zAL&-K!W2{l=`EKB+;Je{3RvV+%2$-6%}`6E-ls<04B{~x=tf6$>a0`a#r1lv9xbr2 z(BemFnqo2ZN0Z$d2wgl-?u8~Ymud=i8@2Mzoc>x3T_mdRh@^Pu)JX-Dsgmk5!jtYo|$4#@8!t}-*S?lAb)w<+(rZ>!57n{x3 z(5UpG$|J+CiOwNX$JHMnufzyro47GdthSh0UO2T0-$HChUkzUSW4jkZr~IuRNf(_m zqdGlF??9tQus=N=dn=v6TKC$wj#&0X{4x)b*!1Wee7gKBW^rA)XG(hA zurvK7tJQ|vW>2b`WU9`-3Ufarspeg#U}0Vr_f#6V!7*e>L2bFz6P<%^TH9M{3`Yw~ z1GRdk+~CCQkxM}u1adm4VU?@tO|Uyo*jdrmgxV zT?#Xha=dD++U=M1L6F(oMYTRV>Ea?iLAi!UhPWIWi&vv8g!^R#$tL678pzOC=i)15 z!8w;Blfg=*7Xv1dlS2;kMFkz$TOL@HiNQq46vUD{gimBuD!kAUS=x;HJ>Rx!WT;#h z*Aj1@JXj<177E#9lIGL5P=|VIlDrU(b}U*H=CIKsn;4Yed7yZlbNpEk+t1ju~?o5q=NUNR=rD{Q^@t^2v+^R{LF$cf<})Sc3Uj(`R@Imig}aD&e;tW>n;x3Ru5xLN7SlX) z4c$i+m73!v7h{K%n0^@wO1PB7WSnlX+`Ijh8xkjFg0GX zNJu%LT50r`d!ln|HUC3(`JfPig8VqS4lB~|I1m$fuFcIPi;>SS1H?-#poq?^)%s{E ziRqRQ#zp62*l5(D5uL9%A9d^xw@J&&{D%-Mae63#@f`8)c4d?cZ7^{T{uoUr(NnLI z(@B>WI-(_t!W%f9i-^J+T$+h+FkuX*K@kd9NpV@g@TM62-oh;6J{gy&qTMBQ=(Q<9r?>LGLyi%W6G+bTn*jUDl#N{>YZ z-5zME_3j!0F$*FUk8_a+G{pqN%#X#4uL<=^io7q$5cgTGmQ=e3M&Os{N@m7yh~JcC zfKW7Bdyz0|f{wC`G-Pslkjzdoznau16G{S3lL-CM9G}>T8|gfSa}Rqh3S1)nlSN9q zUR|g7T%4t3dTv}<$83$b8ABZyA~O$Nvto@X1ZfF2qKiTnf)nxq{KXq|F zCp;OKK|D;yQ2$UT7OAJSt}|r=LfB&&&!YJn-)`EaLcc3G8)mHeanWV$Qrx9T#G_dE zKk$)7A=;AgC=P85VIe5dD-uX1$-FAKC?OYB$SFSQ52>#1ielgp^6OqY1$IG@#G9d9 znxtzyznjaA!C9@X`7$F`0eT}0v_xG!OjEkG_Gj)e6}}LfsbZoO#yzHSB6qH-7ooCr z5T>snuU5Ij&XEf4c=v2^ik`udk*ZxVom^s31R=3&p4JKJ4WWdkOMQk!uOMKV#ypmm zo=j2T91-lqih7`-ox5xoZlOL@DA^0RK{1xi!l4vG(mEDSWKE;d0PUvbST+3E+X!=W$DtY;<(A z!yD-%1xf@=7)MQMg6uMXI2B?J%$o`u6-3sN*lJBV*>b%#b!M(r^9>~eqorEvUZG&* z{PMt1?($+-WS2Abl(U{niMX|{n1Cypl%*b5f=GwrAU|6(6fG+amZN1X3)O?k3G&jx z%~2h(W*>H9VTYZWyVf%o8@s27(N22tPLf{?JMD_km-4+Kuok;? zE6Fk}w~4Oxk;rLzZ?CjDTD~?~&NRa~pc5nea?R@q!&XQ?Gz-=gf6&!MGp1w`LOxH+ z+)Osj=SepU(N>s#pj;N@5I-vNTCOGWz-c>AaucyxuH{-f=M}#Y%OhVd^p!jkXVy1J z8j&SI++?PS?t#l>kT8}Zh`?~BW|*=ei_5gVJe*y!ZU!3|Z2MpoyHa6B+Es>{Q_{CE z%_RCD38q7Lhx;Sb6&YNut7&Gsp>Pqgv@RU@L{5S_P$tJO46xM3}JmpWQ+Dg>!i zM>HE=QAaZIV9`oyK`{eC9bCzB=M=M$EIyyb!{pq8%Ire%U0P0tjx5J2&p0`MlcJ{M zUSCq))4}paY07A2xeso@y_NX*b!t=)X9BshY!PKCK4(PT7aKzAX%$X~@1Ifn_}Hvb za^E++c+-*Jj8`Gxj6Yn}eV82`9o)epTZeRNK^Ztg(rqlhq*PaumIqSy0ImgoD;r0+ zwmGw0Fv1gVnXV+~nmLDaOf09SfOtS9!jdbT5w=uQ(VTPloN^yF3%RX!`T~z65@#%- zWJvBoo+L7E!>q;B38Qz}-h0ftpU+1ij zGdgBx>tb@co^2}h$6|DZGF`~blI{r&8tDlMkSjzQ3tLp-EMg_BOHY`QYu*~O4Ak8b zU!rt@LI-$;`%HJBn7+&TyW*!gvseyDo2yt5fO=I=l&Y>|Qk(9VC=cL~2W=70mWBtJ z)OExpLRjb00z)-x%_6x$)_N;SP7jr90$Xpg*WI-bRED)HstX5%#UHG7X^N_8i)GJP z{=iycCN2BH;;@$3Y}JMGu-vVYH*1q{iLviW(Fv)eRocMfQ6=ZT2Pi#pqnX^cE9jl< z6iQS!yKmmqv9pyH#vscEL2W>Z?b>{qa0XUHYf1dOa0Lzi6jv{BDvzE$23(~DM1^xS%BlX657(dAtc{(mW-93S%tB%emj+{~$9l(d zV+mSbhS+`lby^S?K3qzlu354uJrCK%Rl{Q>jS8BN2t~^Eky0F;;%AK!Tl_*^bfYm` z9t^;s-T!DlxLN_D|7`$-e7F^}#-;|V5n_?c+$|hV7hdH@NDkwgWeZ3j*y3tOYJDWOXu!JeY?Dp$*^p7ziD;o++nPg#J%k0x z#KS66?2|3NDX-$MW1aA@P6X_MPnWap0%1B~JhdQFam18lNzd3pH~VVC!`LV@ysZ6& zv@Y*zA(h#wwyw&GBSX~&rprds6LzlT*RZ6v(tO73MrbGmOe8m88xkq0tY&et$r~n1 z`R#bDJe(98#b7WTCL@wu<+$8vQ>$$gnG&iilyfqxpapkM>b51#>!byfNHnCw^#)y1 zxH>Eq)B56Q5;D!eEfRX#Jl~>7hLeWS-Xh6#j2G%XBO%*piIsA%HEgp=V#Q2#g68!Q z;KcYH%_u@gg2>RNB!7c`k%tkL#aPiU6!m=9oYEHXV}G;58=NqM>q_&{NqS-fAGj@~!qLvxQ+rxiLrW)NNV1tIQit0G5J-mJBE( zLEk78b~udovkRG=CVnmy_PHi`a+KB3DV}^vFC@OBKOAgzhRPs#LQ+ z={5UG0SVJecTDU{=&3au6Mdtqi8zlT^ti_igpOzfjuc|$;#I4)QK(qCrY^Q~jlzk0 z6GtqW*b%Q{1wt>UbA(Qk+qvynE!iZzgyo$)*@R=TsV@nrsq^(F+UhWWJ%JJG&s zNs4l5E@HtYxReC}B!5Z@jb#NB43k99nPlsyssz*Fc4e$K65dbt=Xm^s`wK~5Hm%tz zav}iouiEIr`w-Y#2#=f%h25t}SRV-;CTe+gNwh_x;1y*1h&z(ao-{M8fzU(p^V+z9 z@$~GVQ99p__?c{WVY-rLyVOH2B?U=OC1pP1eXXFKPMc>*4&J9G#WFp$bL%jlKDZX63lE7dOOjG^wJl&6JE{aG&=jBo_&Dz%YD6q4AGK6|*r zHx$lX(lhg7cgb_&6$=(#xZu3S@x_Z*u3EBu*+HIwn7OpkSLvBa5~4A4b!|?3(2C`& zXD+n3g?*Nb2wdmHC(k;0_RLu)&zyB;Jo}6}vu2+(Yxb;J6r8z|F38_!`26_7cy9mN8VjuTu~PMH#70{IEWtZ}hPB2^ zzLj+5>T+ptPP~9bcC~`}o0e>owFI#$t@M_!u+*@Jbu)tz>}2D`V54*P>{+j#b$Vz2 zSm*SEmM&SkI3vgGj#&pSM4YfQGc~oEW1CVt=}4t|mgdQIOy|5ctIwTzMpjM@lH!`V zm?WDbsX6f(Om)-V&WZcS4q7q5p6r2{=OSP1vZ)T)Wn9uyR}CB5C$q8AG8B%?IN>SLd7D(0r)5eWHps&nS4ccDyj^QGrN)hy8sp zw!uK5J=f5n2+GisaX#)HcT%^okD={Zzvr4gH^jT)B#h-vdTk`W-|H3AM164%u9*mI zcmAaeG4?ps#Nyjk>kPf}+2)2xN0je%dm%tN?h}!-Q5iFG4O)lWNJ)VyG4iyFp5Ncx zY9nF1ar0h!`JhG&4Vu@$X=Bi&oz8@De64gAy1*UyoCw{$MnuWANk7T~bv8+u^E~?k znv(CJv@7%{C;VS{RN7=3LL=(_cB#)s>iaAjnU}(S)R7yFCJ(yYpqzWIlk&D_1uFkI z#NMF3(XvkM>@j)~G_!5@sEwXUep;x$`#wmuF${c5(3^q;2A!Em5GQBW?etD8c`)>H zJemGG(!b|g`iORkQjgfUkk9r+6JcP{-g`0mD6odeE__mJ*u*v!B0wURY^|B+?XuYn zI$_&BO2jS6OGtw&o!j{B8nEmj@{thT?qf*s_8GC{69%+1FK%vbr(X9Ac|O^> zbX0nwA#Fm4%=k=7tv%O59=(LdLw+6f#O)>)^IoX9OUfeZ$W8|V2{sSn(WV)^#P;MB z%N@{O`>-$GX;Pbe58ReW-L4T7JtiELEfc@DH8*2UZ zcbgf>hbSxY-6SFK5f(Wr^B{^SIM_ymQg0;2=+Ll>3q;A2sxlDTj~}7nv@_n{pCZd(m{g3R;j0L8PD$i9%xJdW6kocw=Z% z@}!{{)l`7W-28|xe&gW+RZL!YK?l9`8O*s5-bkKWhu{*OMGEP+O~(((D-ab-HTT?* zHo8yrQ-HCvP4l<{MFd+cC_!=5OY=8&BCju6LC~F4a2Mq)&@^3Z-Y9}9gppg3swqsc zF>Y_(OEnvKVUxxoTHYxZ+()syxG$@Ym`hk;byoG}bWmoNq*eEN2dK#0W}$#@e;fBr zSHGG6hO2489ahhMsFg7@9qFETSvO2^HLSFOab!&c>>Yuj8iBXf`u$gHOBPFXdD!TK z+jYCu+P`8K*wASU3p1g5i**QscxT$nKqt9MiMnEc$St8(<4oU*C0(2?2nY)1>~_9O z%>%o|B|8PTp(e7WJEVvfvKn(A(oF>urU}g*;-_r1_vLo+TXCf-4c$f^-MUEv65_zv zLLVojX>L$~@C7D+h~^bLSzB%S7`}SDTl3WRb5+JC8O9o@#BHv;>c8SO9~}-%GM+O} zkicczriSC^UkYQOF6Jg3WttsKk`Q~{L6Ce`ccza_yUuc>YkrX1SJOfFL*wj?G+A8S z#YohB#y4^Qo>{ljjSW-hQ#E=_BLuj)?qv$3Z7|B3&Qu4OHsNHivt7Wf+`+L;J{9(P zl}u`}n+RAE4JJ-9gmz4%D1C*a(a@sdyw2oEgbvP`8V?Sj{U@x^1z(M?6!^wXp{Nw;OAmk>32L0@6pQ=uw7j zv4MQpRiS2`;R?<27g=D|I+f(Kr!7?ZqrQ_off$*EyI$tyZkWBL`FP%GxA8tQ6F4Nw znxeKH-rm$e+G<&q;3EghuZL@u5tO@A>TA1w4NlB;FYY3(Y5%?E zXJsYLOeu|k36;!yf{VJ%!s7Wf09Y-xa@qDu$3;4>;hUO|=H%KPvxI7#7gpY)C5B03 zyLM`p>!rT0slGuQ%OYY}(r7_!z|L6ONc6XWis38XYLk8nwGw;mgrSciiD3$q*+}`8 z<__6BjIGZ~OeAl|7D#|KI;u}Qj|DD%5xaSlN>Dkk<>QDAXp3aORa=TeA-*sZGA`_d zU$WrsD#~R|VU_b$R#*hNEhiH6#sWZTodw{M4W!xcw+LBNQ^s9bGSx)Ow_ztWW=K`& z=S0R4PJ4#RwAq5ucp7h8<5Ccff6H{yR!J(4){9*fBNI2d1?L~0W=XC<6cgdcEHJ-Y zQlNp;yohd=Rg{!;?~?C_=gKKl7q@flPUkw!%`K9g?_wr83RHbutz!s85~16Ug6GoL z&zP1;aId6Cq3TqmTJ-_JQ-%AIFG3#8Oh$3@U4aGilGcV|-Ynuzz6}+alYPrwnlH=j zqs*ofqNc2a>XL{<1og{ktvL^ma(Ou8Gjvalw(RLdALlWhQ{9$kRb(@9ykz0UCZ&|} zts|lL!eiM77lD+vEgh#Bcw`bJS4d+ar4h0iNwrob)tNe)u-cqL_C@2(br{JD7HHo_ zObb-7HQ_$CcHiC;HxcYM4#@ceY4RpaymXD=fkw4cEh2Z8l7nrD4%)S>{^PFtjK{lZ zOg2ZH$%PB9nI_ptBB4w>#rS>6-bfZa0JVtX9!Toz3O7VJ5>2=7W*^w8QS;V9O3uOw zXRPVBsHn)_-ZkdXb9q2+@(4%9>Js8C&9@+3Pf2<+bP)_GP-W{grIX)l4F#!iI{{L# zuE{b9RqnaLem|gj8!v6JD(_GQx~XxQ)faI#(2x5$!n2%(jAOz`4Oxbt9z572Zf~lrwsyAdP)icMxxG-19+`*-^>@dwZhQA7 zDJk(t*L^}SZxkgMo2|bXHuyV1t%K1Z#;lk_ZKaBJL(h)Nt!MEa=J+_%9Tx+%_urc^#eL?)^F@vIqL&sh(71NlW4BJ? zEKD=;663dL%QtaEp2IW!AtjPe{M+l)%saB%K7&=r<#a(AlhPBvyjKT2`RkMQPEsl{ zb`u^Pka8N?4{8*`D2>F{_lpr!^5W#=_!BpXC}%&_LE21ga(A-#Wn45i+WoN2g=IY+ zR@7LWr1@%Du@IF~5MMaP_A2FY!PO5{r zk~9TgW;)dYX_fODI}fHhXxx-A`Il0aX!Xa@~) zVk~#7?~#xU5?1da2EmDFsELWB)6#`fR|x_dMK<_n6_*%~d!cjpeT+>u)x|)=Xx^aeG{^KtEndz% zNYLy@L0h!li{Ubfs0PrXo^oS>A%0#;00F zYeP)q%|bQfg5Z`~T{Ug~fl`KGHs2FbA%svOkS7`-W7Z1PiJI40-{CmKMAp$UPM*P1 zP_%oeE#BO1@mf@}uKgO&FnD;5ky&GfW& zde0yyc$#`G$x~J)3Ac-P(cZ!ua-6Qw@bbHYg!#(87@R6|v|9=n){tcp)n~OVDG%Z$ zi$*OXxi4$WR>&{~2b!l{*6CnSrN=JydRKC<>3QL%D@|&-@(LYt5n8F-EjaJfoi>+jfYX#sB&wP8n4fxlcs#j7vsvC^2+i1GLe?o|9i4&%{xT@3_7EZ=W z%VDZXae|rBP#+GkZ8Ov5PgFmtGhQ)PNVTO(w^xx+BYw+=!R8PGPC zy!F;ZA|(1U?xHgY@-LfXM*g$bNhy~$s_B(rdIN_&$Lsu%CIvNQ$vUlBR93JU8uH7% zbSlz@TN?7TLGwe_wr1W-7DZfb!Q3&`pgt2$d9u*xowCtMy5K>#?0c>;{wcIl-+3Gu zB=1QIQ-UChx4h==spU2Wjc!F78#+LpQS-{&3Yt-~_;XIhJdsy7?zf$+i1f8h{?ft< zMiO>+c-nh0q{G^7gIbZI}}l|&Vq7Rt74)G(W$%)+;%fYjcTePXkWwfhsLXB7gH|9^low$~6l-U;CVWt!Ub<37ga=2H8Hy60vTZ)PeQ+TD zvZtKPUxnFFQf=!Kr7t9l_9V%`OYRtYrcCK9M3Z7Id?XUTmx{gXHcW*`Sqj;8qhLM?)@1&!gaBe<5^UrVuUvXiUZ3NKGOQ#RAGgZIv+D|`&=JK_il5*x?{DM( zp|RgvGl!G1(JZN(%v|WCR|~tIG%qcz;zPppm(YqeDpL7V^&w~EY@G~gklF+lPiMUo zb!8uZ_DywBs~F=`3rj~}b)=xiaHyw9$F-+<=k&ddZUTzzBaPEN5zw|RuUzHC-C%B% zgjH4{^bHB-27H$bW%<~n3eS0&G$N()VKu+yEGe1^ou00 zebvDy@18aB9r+d&r}OFDJFeT(KkuxYS;={loK@)Vik9DyW4b8s5rb$}T2o1>SQsJH}K&3YnDd}J~y#$(7-7_u7r|-+6=Z!`)aI& z1z+TL7+7vSvS?C74?HTvO9pA{=}sIr+SqUPDFy5UbepuvlW55#3>y0V_Op2=oa6Vj z84Gd~KF?~(LYu>GUypE|n9mAHpOo~op;?x1 z{L?Uj)+Px&omNc3IAv={K`Rr&ceX|A8M)q#-kFVK&5Vf`iJrI##n6uSfL&8SQf#c+*ud%0|bcC2mK%yW{yVP`R_oIk% z`b8$szLEczY*LT;nTUD4f7i+fz*4goi7eSXKJ*EOOvwg9LliGSnq<$e)dcq0c%R;F zGwn~F6~a;*DnouOd1_8WDw}V!O>LT)(Xw_xCy6aCB{zE2^Wd^Lx}!y2^if6$p;EDs z@NtzfRcP0~-cP*1xJDqkn#tKTwc&g4wc9(t-L}s8 zX|h|6kr<7pvjK(?X>9pyp_1sn*7F(ZwKQKY)I-?hONI>2Jc!2*&T@M;zP4l^q-?sJ zdDt=+Xrk8>fi+ccNt(;dx_lIvpUz3dkZnd$7uTRNS=>zh6Q?QjuSaH?xG2GHn|qyXk7a({O{p1C z52-!z=WFU!3(R^6P0j#G+8O?G1IG6fcAMoW0TD>_F6*C zCCOZq1BN9nn6Oq&81+3FRwM(1l9iynykyi;^%Hj2+Pp8D@5weO7R-`6!BU&?){qr- zr(uNmIhzAnI4;YnmBlO)8h<0sEpN1%`rVKM1)<-t-z-+LtsLS?R?XB!yY+oyWrWjq zV&2iMpjvWH65iz77F5-8L+OhUINIY6^0E|T{KbTM;oiCiDNL$*7#P^Va@PS~23 zxB;;g60`9q*K(4=H?Jvgk$;xXdCjmDpHZWD4*~ZjXvhWg+0uN_WC=;L*(JFxssXo5*2K8_cN#4R$ z+B{le`+3VZtoHgB6t$u}vH|=e{7f`MedEZaWaf%Y%TF@@|wgv1S5@&4vNaOX*2NZUTeXTy72k3Ik1|PFWdTYXm(pi1?i!XCc zRL=IHx*tJ$n0J`pLzoml+Quu{DTsP|%MBlV`}J8SorR>UBB;WRKrFK!rdLTsua({4 zh?)eRBxh4O_Z{F!Ib>{EezDLX{aUmJ9Hw+~X1V;0f@&Ivac0k$ZG|tS_;l7cK{5+s z(?PO6oFvH=A{4&E(>4FSL~}O$|17QX-aalYxV`n{5r0_Yg#-EyEMh?{#>_NIV8vx>I1$UL?pP;l> zy0)5cwYjGKY`TdqHC~xWw_LBb>oIccb+HF#M2-612PG6V9aH|mxS6W_L_Udn&8eb$ zs?3%Ybe3bUXlao{+g=qrWK@!35_z>`U0V2Qi@`Rm99R7mCuq$v4%#n}P_h<8P==ln zxMf<I%()Kiolkc2DxG;Imggoq`-upgo<@|~% zD1}k?zz+#mU@bDPETQ_MJNiL~yW{X?p+MQ3^ zDML$76FEqG(7sW+Ta@G=BX?1UooeK2)4!Z5l^xfB`sjwB{eJ)3WXy_Fg8xn%5@tFP z+*dJrPrh^!>{a`b${-bT=9polPY~lZo_~U6{ftdoQXhk)H->=&dF76TvRLgd0LRZQ7$>z#_=FQR_6@=!2?Z zDCsmj+ASKTB9<)wX|%o=o-~mA^&jj@yP3WzW9C@Z1fo)m3UW&0mO-j$q1fKPD?;>a zqMuBaWk@DSA4EJ@EaFr+AJ0MVngsJFvHKGOG|n6MeNq6w-E7NQvaK)I*Cv5bjpqC9or}AETQy9apzHg%TB(^jg5?i$Y)ykmCS*bxTATPQ8Jjzy zeKCE2Axa#O#U3}O|z^ZhN3LPW% z#kgk^R`+9K(0Jo3RrKzm&K`bGM7j38%DWaDCSe(rz&5%#r$19}UpX&0CV4USNh@t` zOTk1Npv3U$2LoGKmR?-ys3Z0f2z`UmX&mj9^q$gSK2d^oc|AFoc~An9Eti1ncCYzDkEo&GtVkHMlw~J gw==Kop|M+1{>rw(L^cRT)(xLa(3qu6_VLaC2ePar2><{9 literal 0 HcmV?d00001 diff --git a/cookbook/locale/it/LC_MESSAGES/django.mo b/cookbook/locale/it/LC_MESSAGES/django.mo index 934b7a1b38ec4697d6ad5f1a01b411cb44dd49f5..1c57ffac411fa80778660c36d26f581a5fcfe291 100644 GIT binary patch delta 13353 zcmai(2b>(mm4|y5#a$&NBm|P6waU_J6hS#Blye3|?@aG*quJ?U!mcD+jKG$$$uO7< zBH0*&F=jBqCYYSDIIw`T39`Wi6KoI|jx*f%udbC=n7ivAZ@;SQ>Z(`oy?Rw6zV~+7 zYnPW7UhCTG#}3ctGRNr+bCr(sHsxn}sMT@mk8+$fZ5$_ncT)ddf5&+pHVtr`<0JP_V-{%>ib|jSU$pW4u_R+66^;%!%eU&3}I_{x^4d<>_Gie$Pms?U>oLl zUZgOQhCjlwu*XQpnE@BVDtHd;0&jyA@IffWo`IU^4R{j#1onZeMn#HbpcZsGlp<%t z74Sma{uXS<{LV)dG|}f!E9^DeaazG4uoH|y4KM|+gR`J4bftZN1C&KdwtlaD|Fms? z!SYY`{aa9$+XoBy!09jspTV9GS35rJ36oIocfv040@w{+2W5#np(cLN)}Mk>><>^r zeidrG{+RVpI1FlmQ=rCOI2QXKMq#aONJ4$E1#0C5*cF}&Wy))z2Dlk^hW9{O>PaXC zpMx6sb^HErQ2oDzwXpp$ks@iR1)P2i_U}&N92#7BJ?sV_fl}mUC`Dd}3Yrh0R@~>< zXu^R|3XFqV`DCc?W<&K`Xy31bijDP93N=9~u(LoxADnMrTmq%QPi*@=Py_!CN|7gQ z{Utbu`s=oRz_@6fu}}j~f|_V9)OV|FdmN6Zo`P~o;YJGTcn>@bJ`UHyKS6aEOK+`w zE?frlP%C~6%G6I=z67e`@PrL&ZY7snPpxZ~*n* zQ1i`%1vM?=Rqm71WJ(&wq9rJSttc|Kn--BeSb65 zitmCw;R8@Bei>@~y-iCi-T zYN8QP?USI!nGI#36;O(Kun){Y&3AtEzTjLzK|%9#SPk!hTG3vp0pEqK;m1%W`y6V3 z)^nrwE>J%20X0r9%K=cn9s%|JY^ZS;Kv`r3?4t9(hJpspLak&6l;&qceRzd!zZPnu zUqDTCJJibVg>B%oP$qs6>btjX`v*|t?}PfjY@Xwcgl*tp=6A+XI18Qx2g3K^aj+YI z*2Ci=JI=Wi{sMjq)$jWGjxz{81&6?o;V9U90oN?J1dfI`z@hLZsMslA7;W>zVBrWF z22+q`Godt}2kGl9hO)$^umau)<-^;d`t63w7ki+5{vK5S&tV;GyNCdWA>05jg6-f( zQ1gAh2>YwyUo=$0Hj5)ub+tSi4yL^t%G9f2TUZMa4h@; zveBHuOQPI=GUVWN9$$j}kEiez4c~_wmqwbt0kzUe%N%DKTo19ja~agi{tTzX1|g-<9@kO^nPJK0`q;1<5@xQbQK{)2VV;nAN! zXv6!D;D@w-hCK%}(_0%EkoHa|I?jL7?rtJWQtxw8pnUWzC`Imr8gMt%%HD)hahy!0o%fDP~V*nmFX^q9pF!)TvdYl?pau9Md1|+N|moceeem?K!*g;DOL&P+y1Z} z90S#VGL)~EL!EXtPz(7EJPn=$t6=AoqxYlXOzI2aaCq*?*k796OM@nS5=w#R;V`(@ zws+hdwReYYXdeJ8VYRJ~hZWSPK`FQZ4uLD-QE)qy>92(P{^wAN{c1Dzm#JQ)L5jR% z`6-mo%9GK+ec(LmgP{~mLn*ui>f-T3+kUm>txyx*54GZFp!#)gh~^mp`%@oXppc@l z7Ru+3!C~+f$X0h+^HMI_WSM}K)B~s$=b;qZ0XxC-p)%VpTi*jaQh&?x6DSLmg%Jzw zD9D$cp;pu%9tW$Te3*yR;6LG7I4&J2bRN|Hz6kDuH$x4)@RUfA6;Qj%gSD^@Dn_1z zTHxDokoJGKOw@4_)BrOqkAsI&UkbZG56*xY7=w2}C7{1R4eVqi9sz$#bu`rW`w+^N z9dgk)gP_J856$oY1r$2au-x)Q%gs=x-vVXA?NBQ^3(5r-SY8D?QNIbQ-`!A_c?>ED zUxnRZ+kABH_kx|NFM_?a|Bt6&CW2b&cFS`i8^GBG$HI!nNb_k>QNA3uhZ~^wbpmQ3 zr^0f07Swp>LRn}R3;tKoJx7B~v`VKxP%Bsm^}P=@Q3KSj_>pbD2ukrQp%!>6>qa3Dm-FhqBDWQ2k#iP}oD^eJImB{GDjv zXW-doj`If8N*lIE3T%T?@JCQ9xCBbUt1N#B52OAd>;v~enR*}W37u1;@s5B>Oof3I zwCw_@AWTDpzlT(W!^9!dQL`~E{HML&TWrwmJL+Qm=$L zH`KsW&W;k$cVRX4d!RDiUtv4=E-Zr|!~Sp|lM<~-H1}}3`9>)zIs0@8q@!c@`;G7fSb*g9hgVkvia%8cLSptodjgP=2>3Qi{@T% zf$gM!LdSZ}4am_5u5^Be=#dFuFeUz(4!&f|GwrueQ@;~gNqr7H+O{7Fry(`8J%Q*c zOrfFNcK9w06Oc93kATAwJv)$_kU_M+1wTMWQm%u)LF9th5j_L!SSsJAKRmS&oG)Pw z@2`gQqqc&H#AQ?}crh1-$SKiF^J}*)?Z2lkKMq5DWF~SPaz9c;nxAVZD6l#peOf3& z)gb{olWd!|_bOz8{6CL^_G$AoluqZ`%3}KgS=c-isNYEGD5Mb?Mg49VM@CTo3ETh= zNA%o*JdVVWcC;;rk09C|Pa)?szxn+JoWCQlAg>{lkav)8K2vFU7^!2hb%+v;o-}fp zopibycw*E?!j1?z$~ZpeAbKu9&O-VicOeVy;1tbsspUl4 z+fyD7huc2dx*sFTrgLelMJ7_#^I-(%q=*HRkyh9b)z;aTyHMVWw5R?#91XX@myus0 zZIQQ;dfJad-k_{UDOt}n2#&PMbtkX?Q;d?(@hH@=Gw;RXjp`7r2Z?|4(V>+ITgjd{d%vMoSwR>-gg^(FX^U} zUdn9<6Zxd?ddXzilr>GMAXVpvwWd$jtqF7WZd1UYj2{oue%AF;2{#qy{A_IUi1bu5 z?0SY>88oDmTivXm^y4|#v)$d=OxWP&m@*k;a~hUm{8Wyfje+0fC-x5;X86|2#OqD( zFy*^j!@Nd!*EV@6Mr7JV#;bFKoSO?xr-YvkG7MoBk`A*$E(lXGcYT<5<1EcfW<%FY zBv3~Bnh`uV7v!|wRKkqC4%Jf8xKc7&qsEVCd{5s*gQIa~Yh(t`jpwsDEvk7SGkVOO zr7w)_Qpv4m@HtClCO5#YVKy7oFmKIPGg+PbX+k@V(XS@l;sz(Gb^Kj#HWtRnly+*S2{#+dS8lNciwPwhWoakf58r=^Y@ z^lipVCJ*?imdO*|)@BDB^et;Ms~#VhqRk83-zDy4a3a1#$6T0JD43#$Sq?08rir9f zT$YcA4Gk^{(7W~ixL$)c2St;gkm0m~t=bCvcZn2ep2&F4onLEa|F&6; zl{#j_247JwJxt5eL{M9cvxs$V&uq0O3Nq1Njpl0#aE6yovrmW=O^}K9m6vs!{A3b$ zW1x)R$RK9Sszg4GH;Ck{JJ^ra#oVRFVA@QJgKRuD#B^Jg@)}H#95kD;j9xIh$_H%P zVpT>}yE7P+e%dFfStCDmXz(+2e!}|qlzu&nFZHS_&FuAA`-Sm%m}jZ8!c>Zc!N$!x zGuW$hw9`y!Nj{e`JKEG%=KQoNc8^nb%iI*34Wpu0r1t)0hBYUnN#EkvgI??AuJTD|$^a{THCQ?@P8}J7^vX&f|t5-V6gpC0k zw{*p@$I1!>u)ihE)O7LO*tQ_;*0O_R?(85Dg?4=y68};(9%jfdl0bG)Z}lHH2X{ zr>w;OQd^6Co%ZVdSh3@%H3cuTIT1Fo(X`V!KJX4(kx<#6WJ!wkL}bjJ&%(0GHtc*q zmB1c!(*7rH>uXp040PX90iynwy>?>|qFSw&+S+`o)rPuHsgVG}y=kSZ3b(~$Kg~{b*4x9&#QC=k(VQ)^ zm73V+`M(OBo32jn^!DDM7ug>6i9?7^2{h&M_ne& zr=zBn1cYKnt`t4P7$0r*1=W&&?y5g84|7n`F{6 zXDVe*R6^DcM+7l@;F7ic45r{bOnKE6r{oD*Cg+Bi^Y}EI*8sYVYII%4vdZ-2WlWS0 z1ENHVd3AL`K2@i?ndVOwLK3&ix>knC(Df_QbjEVoc#zUE88uRc(MdSEINFaJL#|7y z{U(zQT8tBoui^PD%Yu`^wrxh8l~|5@X(%%nj8@U0716?FuKfz62oN;TJxuFU4|A*L zPxHjlA&+TwQH{$IX6lwod+7`pb`8`>RA`u7&Z|oXUao+7mgl7qOa3<_@xeFz!th+c z{#Tpk@``{K-or)Mq%H_ECa4%tsjPV+*>r)ys@)m_$wJn-MC{c*z_Vh+N@U%X(-TG!#tyC}gmK!Xz8_ zF^u8^xcQukJq-}Jr{wXWLOl_fTLj-H-CUlVpSH|?rCLNAKk^Rfk_*y-*+VQg(z-Dp z7MS*c#xZxL*>7foK*LA7kvR!?FB#9L!U`!9?Y#XL*Pt5pl3|A1z(JF6W%cm9@`sIo zts6V$tsi0qcNszLHwN1370tKSfJV5AhOlLljTV( z*r)lWHJy%^kRaCP<7kL<$)~tr8iSRdn7y+7pjo7Czm6-fHo9VbkWG@#jA*|Gt~Oio z$R)#$Ae@@hKfy)VY{RXj`Jgmu$^B);6-&FdBUQ$U_i3fimtI#ETY|la4{f=ihWi}> z8Dxkm*-^p89i88+VIB96T-djC+46p6-P!V7QA`TNruIr&ymQ50E0^)ZSHE`17R4)8 z-d!=<+)5QdrRA$Omi6R5iWPFiGTH@XPCH7m=RNU7q*l|K`I5i{ef$5hiyg z2l-^QOwKa{PG7UAys(G_l40?QJbOT6nmZ-|97k{5rZ#M%o2$9Q#@yp@0b!hE76oXK zCb2hvX9iY`v9-tnCZ$<#a?%IQS6FU^p}RsEczDit{vVYijUtt=T6aNt59`kTeu~b< z((sK>l(m`570z>uyO;Ou7saA{$1g!$d&m+>+=@`Hv83Nvao_QU!Xnb4$JIw0mS}3e z*O~;XEx;K=+$G48QEv9=!+vzhvl)d7HC`qM<#Y7gw#`@ri`hFZrlHIKajl)~XItKD zzvWu{&CBa4#>Kk1a&bDrFKZt;m@q5uKJl}*%fgJ@TYO~Gzzzyd7Nz^CS9*8T*s>-3 za*!>E5PL^;IG;HLqsC_I*z2o;huGFV*X;0+7}@{Jhqk_@-rjj-#p`P>Y~OtF`o*#F zRUM4I`7y>%)UdccKCA1JJT+q);?Ly6;sf!$=!a=EDVwZxY2t$N>KSojF>vOv#hhhi zYYt7v++NLwI`|q?99j2jrMb}BnJVi)C>%K2Im5~A>^lCEp%MYHpVA&BDJm;v**($y zBcEi2zA~@^GwX95uvcC>#_J!xNoP(yaqm&5BTkL(4g8uTjJfF(9b_OpGl~t5$+=iH zn2=>I&OX0}UlY2E5f{<4x+!pKF>Ueaphu}PSbfL|o?Dww$vB+*k>wBQY_0-CuD$=t zY7JrEXzv`jLg1{rKnGov@z{a<&PxV08Ckpkb$OFfo8M!V7Ws0bV@@hQVx)ijW`BN?Cm6s?7;{Qj zrJpS;v>5PUhwon(o{+JX>1^kiqgb!SN70T)8Qlyr`84^-ct)LNR?Yx&^Zq+$q##E^ g+T40EKbeDn_S1z|Da;3w+P@9>?+T|8LB&8JlaH>x^9tbKAx&V(yo1UE~%sW@a|bLP!6kVvU zx*?AnQg5FzG1$F^F|U#z6|Guhn%!W`R&0*P@G$n{`ZgL@L0=PN&SKT3#tg!X&AfJ5 zEsR-8xoJyd!nkj1oH5zB8*5@{D`V;y6EIO^)SwlHVml1Su2>!WU^g6swQ&*F#g$kU zH`sa?Yf;{VDR>a8;a`}6)#8omggvn*R$wIkn{8y6w0Re!@KaO=-{V;P9b<7+Yi|H^ zPy=3sRq-**#g(@H9BSadq9$V67!v{!7=cl!`&!^|`ZsOJgyKBgpc1Q7UT({4QP(%x z`fb)X?e+IiOZo*4!f&t|rY0EE5YtiDb1@Rfpe9<10nL0qnd-O%RbGbK_%!N4r;)uf z7f>_uCwdQzL>-eDRJ#tS8K$9DurG$;2-JNAs4bk1T9JDbS$~aa0TmkIa@*h;)D4?) zBEE$hKthr+^{^W@!yMF1rlSV%0BQgap(eBn_55d19d1Rf-_~oFhFbD$RQ*UCh9#&O?!ub5$NCZ0qI?9k65reUD;Q5XP&LJCkc^r^ zI%-9FS_hy`YaZ&sw_7J*Cgo{(C%%Gu&04qfW}J^2(DS$eH`sFL_TF+mFa=vvMhUxvk z$2M4m>S#G?B~}L;81tMhZ$!;#8)^%7Vio)ZwPK&6PWv%iK8@Pri?;kHwxV1u)f-SU zw$l5bK}LsZEUJTY)Qo1MW>AT_xE$Ny4_F7IJ9-_)qh{D1{n!J8TWB4Cqp8nBt=Owr z7k6SnhvOg_&HO8DfG05te@DG;t@+;6z%s49Py^|UkywV&I1l-GFiTMb*o4}$9oDx{ z19%tJ?`NG@e^s2Y73Wbi{vGw88lAlx;!#_Yiuy*&Ky{FZ8o(&j152!PPy=3odj4Y6 zK$fFcYK?V6XVza!xq}Mr)d#2t9!A}88ufq+s4e-!mTPtK>Kmf&i$nbywnGi9V^_YQ zD0fGdNAoUgg(sq(Hw9HcD?mmgnunVC!>9qQMtu>zg292=>xWT?>^n@xpHL5Ol5Pir zDz`(eKxb6@3~O(UraT1IE-;>qmbM5r!)d4i%tI~dqo@(DK@IRF)Q#Iw9qdMRuordT zN2rxMjyh!Dq1yju>-8m}=Y}Hp2TU}X_Ea>&HaGy|aR&Com3TXz#2%Q*9|IfkAEQG4Am%UiMLsB%2kq<_>F*otjr?KMAv}XRRKK7OUDyzBg`!aPH()rX z;2qcZQi0dVOeC`xwb#jc-UBUt%P$5p6_n47)!)v-3k7}Oz8Mr}np(qF*jk%^{aII3X@>H%}HA>NPL zv(=~$H()ew#YjAWYWF49!OJ)gLwWgIU?p-c&3bH$KcWT_d#n0k{}aimWgO~Ho;A(rTrLn|1s1+zQrgEyUh+j(!WV0qdn`2dT=iC zhM3W)fjx^_ku6vcciQ?x)|03XFQI1Y8}7C1jhg8QjKf0IRxL(-qprb#_WTMNc@;I& zDqPh-YNH0w7_|k7*ag#VxeSAc$odd!#!pzE#%RhfpeC>j`{6#+7S$fX`e%`Ogs&$C zZ$3s1B!PEh4W^(T_#tWlpP}B0Q#cXNU_;Cq<^91j8Cz3cifXqDb^qJe1E@3d3F_>e z8pZmjkhx4n491Q29@x`50`#*v89$jbs0W-wE$LOPzy@QznJqyL=n2$7H=&mJP1MTm$22^J8d&T&@9juO zwd;ji>3*m~d?(T_U>+jVl!_NnuhYAzrTGMPXpW+0{w->NzhMKcneUZbqGr|!n`1U= zD<+}tpNSgKT-2dnfolH@M(F+DN=C26Uerhr2QSdEEuTYe$t6@fA768NKs0J4;!y+a zj9S|MsCId%flfr7ox4#JSbM-?3z4t?`V^A}gYOhzK z2DAj#!79{@wx9-bzi#iFs?#PXj_2H9b^t*4@{cs zeKk(TFv@399sPpZl0Pv5!%Mw#47Q}4jM{=>sP+@>^%B&3KG(VoGbz7{>M!sk8J=lU zm^NR_=1F`Ue?=C-JT%Sg;0kJ`VyAmI=3{rtYcUy*q91F{@D6hXa+Xa4jKfB#Gt>k1 z8s3hqNWc`3QNyZy+=3az5aNE~6GG`Ckwf%Xfs{j(C-*Nt;V} zEp4}%1nNiGe3p;>A7BezP-j5P_a^Z_;y*+qZul?$ohWys5Q<8(2pz(56-Ye^orPzJ zc7#&4hiS|`U2R^>r~hEexdD5FdCDH^B^C&(={6%aa zo+gxLdIUe4@_CBj3orP`Wn{3Hf7>BHCx53XI=PopO=2%`f~ZF*y+;K5Z$P8k6dDmX z5lV}Qal~?B8==&g7)sP3^zQ$I=uA9LR43~3oM+J?dJy}G7Sy%J!9*WoB(Z}SPLTNh z=kvEiQB75}gR8lODm(mV5?JH;y0< z5>Z4yVlwd<@wLA2&y(3iTuUF3i6d^JlP*L2OJ#31rj38gaP1>$8DY;xa- zYgnURK|!-2Gs~wJl^2yxH9aZil}{*hTeK_oxf|OL@Hw%mN1Vux?>nbDR=Tr0)$ln> zI_JAhyX^7RESg%_EO)~AqOu7y-14+Oe)ofnJABT_?s@BGXZoClJ@z_dvl=*otPAeu z8$0@(^F3!frM=Re?Y-jMv%NxnuCMpkzL1h}Q>Hi}*{hwGv$wey`@ZIPLkGtBowUIv z&hEjR+-gIY`J9Jy+PD=tA^uu}#!W4pIj(R*Mzf-FXLjC5=j*(-?t Date: Tue, 23 Feb 2021 20:56:53 +0100 Subject: [PATCH 33/96] added some info to .env for DB_OPTIONS --- .env.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.template b/.env.template index 1146dd9f..29078208 100644 --- a/.env.template +++ b/.env.template @@ -13,7 +13,7 @@ TIMEZONE=Europe/Berlin # add only a database password if you want to run with the default postgres, otherwise change settings accordingly DB_ENGINE=django.db.backends.postgresql -# DB_OPTIONS= {} +# DB_OPTIONS= {} # e.g. {"sslmode":"require"} to enable ssl POSTGRES_HOST=db_recipes POSTGRES_PORT=5432 POSTGRES_USER=djangouser From 205f76d12896c80e2c531c31b836c4bd4911fd3d Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Tue, 23 Feb 2021 21:43:14 +0100 Subject: [PATCH 34/96] fix that does not really fix anything see #453/454 --- cookbook/templates/shopping_list.html | 2 ++ cookbook/views/views.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cookbook/templates/shopping_list.html b/cookbook/templates/shopping_list.html index 4dcd36d8..c52414d0 100644 --- a/cookbook/templates/shopping_list.html +++ b/cookbook/templates/shopping_list.html @@ -542,6 +542,7 @@ this.loadShoppingList() {% if recipes %} + this.loading = true this.edit_mode = true let loadingRecipes = [] @@ -605,6 +606,7 @@ }) }, loadInitialRecipe: function (recipe, servings) { + servings = 1 //TODO temporary until i can actually fix the servings for this #453 return this.$http.get('{% url 'api:recipe-detail' 123456 %}'.replace('123456', recipe)).then((response) => { this.addRecipeToList(response.data, servings) }).catch((err) => { diff --git a/cookbook/views/views.py b/cookbook/views/views.py index bb122d70..9402efb0 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -252,7 +252,7 @@ def shopping_list(request, pk=None): if re.match(r'^([0-9])+,([0-9])+[.]*([0-9])*$', r): rid, multiplier = r.split(',') if recipe := Recipe.objects.filter(pk=int(rid)).first(): - recipes.append({'recipe': recipe.id, 'multiplier': multiplier}) + recipes.append({'recipe': recipe.id, 'servings': multiplier}) edit = True if 'edit' in request.GET and request.GET['edit'] == 'true' else False From 2c34425135d0d8a9946bd6df92197d6f81f6a868 Mon Sep 17 00:00:00 2001 From: Greg Smith Date: Wed, 24 Feb 2021 17:36:06 -0500 Subject: [PATCH 35/96] Remove fixed height rule --- vue/src/apps/RecipeView/RecipeView.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vue/src/apps/RecipeView/RecipeView.vue b/vue/src/apps/RecipeView/RecipeView.vue index 9278420e..43cd0a16 100644 --- a/vue/src/apps/RecipeView/RecipeView.vue +++ b/vue/src/apps/RecipeView/RecipeView.vue @@ -24,7 +24,7 @@
-
+
@@ -36,7 +36,7 @@
-
+
@@ -48,7 +48,7 @@
-
+
From 21740522bcc3448a27ac63615e5e4ea082da9a0c Mon Sep 17 00:00:00 2001 From: smilerz Date: Wed, 24 Feb 2021 20:13:06 -0600 Subject: [PATCH 36/96] fixed URL import when ingredient is a string --- cookbook/helper/recipe_url_import.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cookbook/helper/recipe_url_import.py b/cookbook/helper/recipe_url_import.py index 139b20ab..3a734d84 100644 --- a/cookbook/helper/recipe_url_import.py +++ b/cookbook/helper/recipe_url_import.py @@ -69,8 +69,10 @@ def find_recipe_json(ld_json, url): if 'recipeIngredient' in ld_json: # some pages have comma separated ingredients in a single array entry if (len(ld_json['recipeIngredient']) == 1 - and len(ld_json['recipeIngredient'][0]) > 30): + and type(ld_json['recipeIngredient']) == list): ld_json['recipeIngredient'] = ld_json['recipeIngredient'][0].split(',') # noqa: E501 + elif type(ld_json['recipeIngredient']) == str: + ld_json['recipeIngredient'] = ld_json['recipeIngredient'].split(',') for x in ld_json['recipeIngredient']: if '\n' in x: From f2630c3ba0a1d8e7fa3a2f178c765c8090ea1b9a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Feb 2021 06:02:05 +0000 Subject: [PATCH 37/96] Bump markdown from 3.3.3 to 3.3.4 Bumps [markdown](https://github.com/Python-Markdown/markdown) from 3.3.3 to 3.3.4. - [Release notes](https://github.com/Python-Markdown/markdown/releases) - [Commits](https://github.com/Python-Markdown/markdown/compare/3.3.3...3.3.4) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 17b742ba..1e0e5120 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ djangorestframework==3.12.2 drf-writable-nested==0.6.2 gunicorn==20.0.4 lxml==4.6.2 -Markdown==3.3.3 +Markdown==3.3.4 Pillow==8.1.0 psycopg2-binary==2.8.6 python-dotenv==0.15.0 From 59b2da933da4be8a5084134e3b679777567c8c29 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 25 Feb 2021 08:27:22 +0100 Subject: [PATCH 38/96] fixed tests --- cookbook/static/vue/js/recipe_view.js | 2 +- cookbook/tests/api/test_api_keyword.py | 2 +- cookbook/tests/other/test_edits_recipe.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cookbook/static/vue/js/recipe_view.js b/cookbook/static/vue/js/recipe_view.js index 28609447..2f5efe25 100644 --- a/cookbook/static/vue/js/recipe_view.js +++ b/cookbook/static/vue/js/recipe_view.js @@ -1 +1 @@ -(function(e){function t(t){for(var i,r,o=t[0],c=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),o=s("5f5b"),c=(s("2dd8"),s("bc3a")),l=s.n(c),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},g=[],b=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,b,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.number))}})},E=[],T={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},$=T,P=Object(C["a"])($,S,E,!1,null,null,null),M=P.exports,z={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:M},template:"
".concat(this.code,"
")})}},N=z,D=Object(C["a"])(N,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),H=s.n(U);i["default"].prototype.moment=H.a;var I={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=H()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=H()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},A=I,L=Object(C["a"])(A,v,g,!1,null,null,null),B=L.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:H()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,oe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("img",{attrs:{src:e.pdfUrl,width:"100%",height:"700px",alt:e._("External Recipe Image")}})])},ce=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,oe,ce,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.calories))}}),e._v(" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.fats))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.proteins))}}),e._v(" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,ge=Object(C["a"])(ve,ue,me,!1,null,null,null),be=ge.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,Te=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),$e=Te.exports,Pe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Me=[],ze=s("8e5f"),Ne=s.n(ze);i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Ne.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,Pe,Me,!1,null,null,null)),He=Ue.exports;i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var Ie={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:B,RecipeContextMenu:ee,Nutrition:be,Keywords:we,LoadingSpinner:$e,AddRecipeToBook:He},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var o,c=Object(r["a"])(n.ingredients);try{for(c.s();!(o=c.n()).done;){var l=o.value;t.$set(l,"checked",!1)}}catch(d){c.e(d)}finally{c.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=H()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var o=i.value;o.id===e.id&&this.$set(o,"checked",!o.checked)}}catch(c){n.e(c)}finally{n.f()}}}catch(c){s.e(c)}finally{s.f()}}}},Ae=Ie,Le=Object(C["a"])(Ae,a,n,!1,null,null,null),Be=Le.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Be)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return o})),s.d(t,"e",(function(){return c})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var o=(i+n)/(a+r);if(e===o){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var c=Math.floor(i/a);return[c,i-c*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var o={methods:{_:function(e){return c(e)}}};function c(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("use_fractions")){var s="",i=a(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file +(function(e){function t(t){for(var i,r,o=t[0],c=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),o=s("5f5b"),c=(s("2dd8"),s("bc3a")),l=s.n(c),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},b=[],g=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,g,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.number))}})},E=[],T={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},$=T,P=Object(C["a"])($,S,E,!1,null,null,null),M=P.exports,z={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:M},template:"
".concat(this.code,"
")})}},N=z,D=Object(C["a"])(N,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),H=s.n(U);i["default"].prototype.moment=H.a;var I={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=H()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=H()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},A=I,L=Object(C["a"])(A,v,b,!1,null,null,null),B=L.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:H()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,oe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("img",{attrs:{src:e.pdfUrl,width:"100%",height:"700px",alt:e._("External Recipe Image")}})])},ce=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,oe,ce,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.calories))}}),e._v(" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.fats))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.proteins))}}),e._v(" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,be=Object(C["a"])(ve,ue,me,!1,null,null,null),ge=be.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,Te=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),$e=Te.exports,Pe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Me=[],ze=s("8e5f"),Ne=s.n(ze);i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Ne.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,Pe,Me,!1,null,null,null)),He=Ue.exports;i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var Ie={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:B,RecipeContextMenu:ee,Nutrition:ge,Keywords:we,LoadingSpinner:$e,AddRecipeToBook:He},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var o,c=Object(r["a"])(n.ingredients);try{for(c.s();!(o=c.n()).done;){var l=o.value;t.$set(l,"checked",!1)}}catch(d){c.e(d)}finally{c.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=H()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var o=i.value;o.id===e.id&&this.$set(o,"checked",!o.checked)}}catch(c){n.e(c)}finally{n.f()}}}catch(c){s.e(c)}finally{s.f()}}}},Ae=Ie,Le=Object(C["a"])(Ae,a,n,!1,null,null,null),Be=Le.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Be)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return o})),s.d(t,"e",(function(){return c})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var o=(i+n)/(a+r);if(e===o){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var c=Math.floor(i/a);return[c,i-c*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var o={methods:{_:function(e){return c(e)}}};function c(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("use_fractions")){var s="",i=a(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file diff --git a/cookbook/tests/api/test_api_keyword.py b/cookbook/tests/api/test_api_keyword.py index ffc2bb40..6e870f32 100644 --- a/cookbook/tests/api/test_api_keyword.py +++ b/cookbook/tests/api/test_api_keyword.py @@ -80,7 +80,7 @@ class TestApiKeyword(TestViews): ) response = json.loads(r.content) self.assertEqual(r.status_code, 201) - self.assertEqual(response['name'], {self.keyword_1.name}) + self.assertEqual(response['name'], self.keyword_1.name) def test_keyword_delete(self): r = self.user_client_1.delete( diff --git a/cookbook/tests/other/test_edits_recipe.py b/cookbook/tests/other/test_edits_recipe.py index a1ba3944..288f5607 100755 --- a/cookbook/tests/other/test_edits_recipe.py +++ b/cookbook/tests/other/test_edits_recipe.py @@ -14,7 +14,7 @@ class TestEditsRecipe(TestBase): {'file': 'cookbook/tests/resources/websites/ld_json_2.html', 'result_length': 1525}, {'file': 'cookbook/tests/resources/websites/ld_json_3.html', 'result_length': 1644}, {'file': 'cookbook/tests/resources/websites/ld_json_4.html', 'result_length': 1744}, - {'file': 'cookbook/tests/resources/websites/ld_json_itemList.html', 'result_length': 3221}, + {'file': 'cookbook/tests/resources/websites/ld_json_itemList.html', 'result_length': 3222}, {'file': 'cookbook/tests/resources/websites/ld_json_multiple.html', 'result_length': 1621}, {'file': 'cookbook/tests/resources/websites/micro_data_1.html', 'result_length': 1094}, {'file': 'cookbook/tests/resources/websites/micro_data_2.html', 'result_length': 1453}, From d01f7409bf95b081b369d9cd6a76cc6a6861c3f9 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 25 Feb 2021 16:44:42 +0100 Subject: [PATCH 39/96] removed django-random-queryset the looping strategy is not efficient when using spacing as ids for a single user might be spaced far apart. A single user also only has a few hundred recipes so using the order by ? method should be more efficient and also automatically be compatible with spaces --- cookbook/views/api.py | 18 ++++++------------ requirements.txt | 1 - 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 59c8b261..d192dbd8 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -4,25 +4,20 @@ import re import uuid import requests +from PIL import Image from annoying.decorators import ajax_request from annoying.functions import get_object_or_None from django.contrib import messages from django.contrib.auth.models import User -from django.core import management from django.core.exceptions import FieldError, ValidationError from django.core.files import File from django.db.models import Q from django.http import FileResponse, HttpResponse, JsonResponse from django.shortcuts import redirect -from django.utils import timezone -from django.utils.formats import date_format from django.utils.translation import gettext as _ from icalendar import Calendar, Event -from PIL import Image -from rest_framework import decorators, permissions, viewsets +from rest_framework import decorators, viewsets from rest_framework.exceptions import APIException, PermissionDenied -from rest_framework.mixins import (ListModelMixin, RetrieveModelMixin, - UpdateModelMixin, CreateModelMixin) from rest_framework.parsers import MultiPartParser from rest_framework.response import Response from rest_framework.viewsets import ViewSetMixin @@ -59,7 +54,7 @@ from recipes.settings import DEMO class StandardFilterMixin(ViewSetMixin): def get_queryset(self): - queryset = self.queryset.filter(userpreference__space=self.request.user.userpreference.space) + queryset = self.queryset query = self.request.query_params.get('query', None) if query is not None: queryset = queryset.filter(name__icontains=query) @@ -77,7 +72,7 @@ class StandardFilterMixin(ViewSetMixin): random = self.request.query_params.get('random', False) if limit is not None: if random: - queryset = queryset.random(int(limit)) + queryset = queryset.order_by("?")[:limit] else: queryset = queryset[:int(limit)] return queryset @@ -289,14 +284,13 @@ class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin): permission_classes = [CustomIsShare | CustomIsGuest] def get_queryset(self): - if self.request.space: - self.queryset = self.queryset.filter(space=self.request.space) + self.queryset = self.queryset.filter(space=self.request.space) internal = self.request.query_params.get('internal', None) if internal: self.queryset = self.queryset.filter(internal=True) - return self.queryset + return super().get_queryset() # TODO write extensive tests for permissions diff --git a/requirements.txt b/requirements.txt index 05098483..a7488f62 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,7 +26,6 @@ pyyaml==5.4.1 uritemplate==3.0.1 beautifulsoup4==4.9.3 microdata==0.7.1 -django-random-queryset==0.1.3 Jinja2==2.11.3 django-webpack-loader==0.7.0 django-js-reverse==0.9.1 From 74e731e3345e571bc4960b7aa1381aad7934e8cc Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 25 Feb 2021 16:45:47 +0100 Subject: [PATCH 40/96] inject space context into serializer writes --- cookbook/serializer.py | 46 +++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 7eb5523a..e4b7bffe 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -40,12 +40,19 @@ class CustomDecimalField(serializers.Field): raise ValidationError('A valid number is required') -class CreateWithSpaceMixin(Serializer): +class SpacedModelSerializer(serializers.ModelSerializer): def create(self, validated_data): validated_data['space'] = self.context['request'].space return super().create(validated_data) +class MealTypeSerializer(SpacedModelSerializer): + class Meta: + model = MealType + fields = ('id', 'name', 'order', 'created_by') + read_only_fields = ('space',) + + class UserNameSerializer(WritableNestedModelSerializer): username = serializers.SerializerMethodField('get_user_label') @@ -68,7 +75,7 @@ class UserPreferenceSerializer(serializers.ModelSerializer): read_only_fields = ['user'] -class StorageSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): +class StorageSerializer(SpacedModelSerializer): class Meta: model = Storage fields = ( @@ -82,7 +89,7 @@ class StorageSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): } -class SyncSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): +class SyncSerializer(SpacedModelSerializer): class Meta: model = Sync fields = ( @@ -91,7 +98,7 @@ class SyncSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): ) -class SyncLogSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): +class SyncLogSerializer(SpacedModelSerializer): class Meta: model = SyncLog fields = ('id', 'sync', 'status', 'msg', 'created_at') @@ -154,7 +161,7 @@ class SupermarketCategorySerializer(UniqueFieldsMixin, WritableNestedModelSerial fields = ('id', 'name') -class SupermarketCategoryRelationSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): +class SupermarketCategoryRelationSerializer(SpacedModelSerializer): category = SupermarketCategorySerializer() class Meta: @@ -162,7 +169,7 @@ class SupermarketCategoryRelationSerializer(serializers.ModelSerializer, CreateW fields = ('id', 'category', 'supermarket', 'order') -class SupermarketSerializer(UniqueFieldsMixin, serializers.ModelSerializer, CreateWithSpaceMixin): +class SupermarketSerializer(UniqueFieldsMixin, SpacedModelSerializer): category_to_supermarket = SupermarketCategoryRelationSerializer(many=True, read_only=True) class Meta: @@ -262,7 +269,7 @@ class RecipeImageSerializer(WritableNestedModelSerializer): fields = ['image', ] -class RecipeImportSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): +class RecipeImportSerializer(SpacedModelSerializer): class Meta: model = RecipeImport fields = '__all__' @@ -274,7 +281,7 @@ class CommentSerializer(serializers.ModelSerializer): fields = '__all__' -class RecipeBookSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): +class RecipeBookSerializer(SpacedModelSerializer): class Meta: model = RecipeBook fields = '__all__' @@ -287,14 +294,7 @@ class RecipeBookEntrySerializer(serializers.ModelSerializer): fields = '__all__' -class MealTypeSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): - class Meta: - model = MealType - fields = ('name', 'order', 'created_by') - read_only_fields = ('space',) - - -class MealPlanSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): +class MealPlanSerializer(SpacedModelSerializer): recipe_name = serializers.ReadOnlyField(source='recipe.name') meal_type_name = serializers.ReadOnlyField(source='meal_type.name') note_markdown = serializers.SerializerMethodField('get_note_markdown') @@ -312,7 +312,7 @@ class MealPlanSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): ) -class ShoppingListRecipeSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): +class ShoppingListRecipeSerializer(SpacedModelSerializer): recipe_name = serializers.ReadOnlyField(source='recipe.name') servings = CustomDecimalField() @@ -322,7 +322,7 @@ class ShoppingListRecipeSerializer(serializers.ModelSerializer, CreateWithSpaceM read_only_fields = ('id',) -class ShoppingListEntrySerializer(WritableNestedModelSerializer, CreateWithSpaceMixin): +class ShoppingListEntrySerializer(SpacedModelSerializer): food = FoodSerializer(allow_null=True) unit = UnitSerializer(allow_null=True, required=False) amount = CustomDecimalField() @@ -340,12 +340,16 @@ class ShoppingListEntryCheckedSerializer(serializers.ModelSerializer): fields = ('id', 'checked') -class ShoppingListSerializer(WritableNestedModelSerializer, CreateWithSpaceMixin): +class ShoppingListSerializer(WritableNestedModelSerializer): recipes = ShoppingListRecipeSerializer(many=True, allow_null=True) entries = ShoppingListEntrySerializer(many=True, allow_null=True) shared = UserNameSerializer(many=True) supermarket = SupermarketSerializer(allow_null=True) + def create(self, validated_data): + validated_data['space'] = self.context['request'].space + return super().create(validated_data) + class Meta: model = ShoppingList fields = ( @@ -364,7 +368,7 @@ class ShoppingListAutoSyncSerializer(WritableNestedModelSerializer): read_only_fields = ('id',) -class ShareLinkSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): +class ShareLinkSerializer(SpacedModelSerializer): class Meta: model = ShareLink fields = '__all__' @@ -382,7 +386,7 @@ class CookLogSerializer(serializers.ModelSerializer): read_only_fields = ('id', 'created_by') -class ViewLogSerializer(serializers.ModelSerializer, CreateWithSpaceMixin): +class ViewLogSerializer(SpacedModelSerializer): class Meta: model = ViewLog fields = '__all__' From 94c9185bcf60269c31cb4dbf62b20432c4aaaf29 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Thu, 25 Feb 2021 18:59:22 +0000 Subject: [PATCH 41/96] Apply translations in nl translation completed for the source file '/cookbook/locale/en/LC_MESSAGES/django.po' on the 'nl' language. --- cookbook/locale/nl/LC_MESSAGES/django.po | 529 ++++++----------------- 1 file changed, 137 insertions(+), 392 deletions(-) diff --git a/cookbook/locale/nl/LC_MESSAGES/django.po b/cookbook/locale/nl/LC_MESSAGES/django.po index 63ed5447..ac7b8e42 100644 --- a/cookbook/locale/nl/LC_MESSAGES/django.po +++ b/cookbook/locale/nl/LC_MESSAGES/django.po @@ -2,12 +2,12 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # 31a3ead7f9b1ec8ada1a36808eee4069_988cec9 <9478557dfb8b6cd81570ee9e754f1719_904168>, 2020 # Frank Engbers , 2020 # kampsj , 2021 -# +# #, fuzzy msgid "" msgstr "" @@ -16,12 +16,11 @@ msgstr "" "POT-Creation-Date: 2021-02-09 18:01+0100\n" "PO-Revision-Date: 2020-06-02 19:28+0000\n" "Last-Translator: kampsj , 2021\n" -"Language-Team: Dutch (https://www.transifex.com/django-recipes/teams/110507/" -"nl/)\n" -"Language: nl\n" +"Language-Team: Dutch (https://www.transifex.com/django-recipes/teams/110507/nl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: .\cookbook\filters.py:22 .\cookbook\templates\base.html:87 @@ -88,7 +87,7 @@ msgstr "" #: .\cookbook\forms.py:55 msgid "Makes the navbar stick to the top of the page." -msgstr "" +msgstr "Zet de navbar vast aan de bovenkant van de pagina." #: .\cookbook\forms.py:71 msgid "" @@ -127,10 +126,8 @@ msgid "Storage UID" msgstr "Opslag UID" #: .\cookbook\forms.py:117 -#, fuzzy -#| msgid "Number of Days" msgid "Number of servings" -msgstr "Aantal dagen" +msgstr "Porties" #: .\cookbook\forms.py:128 msgid "" @@ -142,7 +139,7 @@ msgstr "" #: .\cookbook\forms.py:143 msgid "Default" -msgstr "" +msgstr "Standaard waarde" #: .\cookbook\forms.py:162 msgid "New Unit" @@ -190,11 +187,11 @@ msgstr "Laat leeg voor nextcloud en vul de api token in voor dropbox." #: .\cookbook\forms.py:244 msgid "" -"Leave empty for dropbox and enter only base url for nextcloud (/remote." -"php/webdav/ is added automatically)" +"Leave empty for dropbox and enter only base url for nextcloud " +"(/remote.php/webdav/ is added automatically)" msgstr "" -"Laat leeg voor dropbox en vul enkel de base url voor nextcloud in. (/" -"remote.php/webdav/ wordt automatisch toegevoegd.)" +"Laat leeg voor dropbox en vul enkel de base url voor nextcloud in. " +"(/remote.php/webdav/ wordt automatisch toegevoegd.)" #: .\cookbook\forms.py:263 msgid "Search String" @@ -211,17 +208,17 @@ msgstr "Je moet minimaal één recept of titel te specificeren." #: .\cookbook\forms.py:312 msgid "You can list default users to share recipes with in the settings." msgstr "" -"Je kan in de instellingen standaard gebruikers in stellen om de recepten met " -"te delen." +"Je kan in de instellingen standaard gebruikers in stellen om de recepten met" +" te delen." #: .\cookbook\forms.py:313 #: .\cookbook\templates\forms\edit_internal_recipe.html:377 msgid "" -"You can use markdown to format this field. See the docs here" +"You can use markdown to format this field. See the docs here" msgstr "" -"Je kunt markdown gebruiken om dit veld te op te maken. Bekijk de documentatie hier." +"Je kunt markdown gebruiken om dit veld te op te maken. Bekijk de documentatie hier." #: .\cookbook\forms.py:328 msgid "A username is not required, if left blank the new user can choose one." @@ -257,8 +254,8 @@ msgstr "" #: .\cookbook\helper\recipe_url_import.py:53 msgid "" -"The requested site does not provide any recognized data format to import the " -"recipe from." +"The requested site does not provide any recognized data format to import the" +" recipe from." msgstr "" "De opgevraagde site biedt geen bekend gegevensformaat aan om het recept van " "te importeren." @@ -272,6 +269,7 @@ msgid "" "Importer expected a .zip file. Did you choose the correct importer type for " "your data ?" msgstr "" +"De importtool verwachtte een .zip bestand. Heb je het juiste type gekozen?" #: .\cookbook\integration\safron.py:23 #: .\cookbook\templates\forms\edit_internal_recipe.html:65 @@ -281,8 +279,6 @@ msgid "Servings" msgstr "Porties" #: .\cookbook\integration\safron.py:25 -#, fuzzy -#| msgid "Waiting time ~" msgid "Waiting time" msgstr "Wachttijd" @@ -299,7 +295,7 @@ msgstr "Kookboek" #: .\cookbook\integration\safron.py:31 msgid "Section" -msgstr "" +msgstr "Sectie" #: .\cookbook\migrations\0047_auto_20200602_1133.py:12 msgid "Breakfast" @@ -395,37 +391,35 @@ msgstr "Inloggen" #: .\cookbook\templates\account\login.html:13 #: .\cookbook\templates\account\login.html:28 msgid "Sign In" -msgstr "" +msgstr "Log in" #: .\cookbook\templates\account\login.html:38 msgid "Social Login" -msgstr "" +msgstr "Socials login" #: .\cookbook\templates\account\login.html:39 msgid "You can use any of the following providers to sign in." -msgstr "" +msgstr "Je kan een van de volgende providers gebruiken om in te loggen." #: .\cookbook\templates\account\logout.html:5 #: .\cookbook\templates\account\logout.html:9 #: .\cookbook\templates\account\logout.html:18 msgid "Sign Out" -msgstr "" +msgstr "Log uit" #: .\cookbook\templates\account\logout.html:11 -#, fuzzy -#| msgid "Are you sure that you want to merge these two units?" msgid "Are you sure you want to sign out?" -msgstr "Weet je zeker dat je deze twee eenheden wil samenvoegen?" +msgstr "Weet je zeker dat je uit wil loggen?" #: .\cookbook\templates\account\password_reset.html:5 #: .\cookbook\templates\account\password_reset_done.html:5 msgid "Password Reset" -msgstr "" +msgstr "Wachtwoord reset" #: .\cookbook\templates\account\password_reset.html:9 #: .\cookbook\templates\account\password_reset_done.html:9 msgid "Password reset is not implemented for the time being!" -msgstr "" +msgstr "Wachtwoord reset is nog niet geïmplementeerd!" #: .\cookbook\templates\account\signup.html:5 msgid "Register" @@ -555,8 +549,8 @@ msgid "" "On this Page you can manage all storage folder locations that should be " "monitored and synced." msgstr "" -"Op deze pagina kaan je alle opslag mappen die gesynchroniseerd en gemonitord " -"worden beheren." +"Op deze pagina kaan je alle opslag mappen die gesynchroniseerd en gemonitord" +" worden beheren." #: .\cookbook\templates\batch\monitor.html:16 msgid "The path must be in the following format" @@ -643,20 +637,16 @@ msgid "Waiting Time" msgstr "Wachttijd" #: .\cookbook\templates\forms\edit_internal_recipe.html:68 -#, fuzzy -#| msgid "Servings" msgid "Servings Text" -msgstr "Porties" +msgstr "Porties tekst" #: .\cookbook\templates\forms\edit_internal_recipe.html:79 msgid "Select Keywords" msgstr "Selecteer sleutelwoorden" #: .\cookbook\templates\forms\edit_internal_recipe.html:93 -#, fuzzy -#| msgid "Nutrition" msgid "Description" -msgstr "Voedingswaarde" +msgstr "Beschrijving" #: .\cookbook\templates\forms\edit_internal_recipe.html:108 msgid "Nutrition" @@ -772,7 +762,7 @@ msgstr "Hoeveelheid inschakelen" #: .\cookbook\templates\forms\edit_internal_recipe.html:348 msgid "Copy Template Reference" -msgstr "" +msgstr "Kopieer sjabloon referentie" #: .\cookbook\templates\forms\edit_internal_recipe.html:374 #: .\cookbook\templates\url_import.html:177 @@ -820,18 +810,14 @@ msgstr "Ingrediënten bewerken" #: .\cookbook\templates\forms\ingredients.html:16 msgid "" "\n" -" The following form can be used if, accidentally, two (or more) units " -"or ingredients where created that should be\n" +" The following form can be used if, accidentally, two (or more) units or ingredients where created that should be\n" " the same.\n" -" It merges two units or ingredients and updates all recipes using " -"them.\n" +" It merges two units or ingredients and updates all recipes using them.\n" " " msgstr "" "\n" -"Het volgende formulier kan worden gebruikt wanneer per ongeluk twee (of " -"meer) eenheden of ingrediënten zijn gecreëerd dat eigenlijk hetzelfde zijn.\n" -"Het doet de twee eenheden of ingrediënten samenvoegen en alle bijbehorende " -"recepten updaten." +"Het volgende formulier kan worden gebruikt wanneer per ongeluk twee (of meer) eenheden of ingrediënten zijn gecreëerd dat eigenlijk hetzelfde zijn.\n" +"Het doet de twee eenheden of ingrediënten samenvoegen en alle bijbehorende recepten updaten." #: .\cookbook\templates\forms\ingredients.html:24 #: .\cookbook\templates\stats.html:26 @@ -953,22 +939,16 @@ msgstr "Veiligheidswaarschuwing" #: .\cookbook\templates\include\storage_backend_warning.html:5 msgid "" "\n" -" The Password and Token field are stored as plain text " -"inside the database.\n" -" This is necessary because they are needed to make API requests, but " -"it also increases the risk of\n" +" The Password and Token field are stored as plain text inside the database.\n" +" This is necessary because they are needed to make API requests, but it also increases the risk of\n" " someone stealing it.
\n" -" To limit the possible damage tokens or accounts with limited access " -"can be used.\n" +" To limit the possible damage tokens or accounts with limited access can be used.\n" " " msgstr "" "\n" -"Het wachtwoord en token veld worden als plain text in de " -"database opgeslagen.\n" -"Dit is benodigd omdat deze benodigd zijn voor de API requests, Echter " -"verhoogd dit ook het risico van diefstal.
\n" -"Om mogelijke schade te beperken kunt u gebruik maken van account met " -"gelimiteerde toegang." +"Het wachtwoord en token veld worden als plain text in de database opgeslagen.\n" +"Dit is benodigd omdat deze benodigd zijn voor de API requests, Echter verhoogd dit ook het risico van diefstal.
\n" +"Om mogelijke schade te beperken kunt u gebruik maken van account met gelimiteerde toegang." #: .\cookbook\templates\index.html:29 msgid "Search recipe ..." @@ -1011,26 +991,17 @@ msgstr "Markdown informatie" #: .\cookbook\templates\markdown_info.html:14 msgid "" "\n" -" Markdown is lightweight markup language that can be used to format " -"plain text easily.\n" -" This site uses the Python Markdown library to\n" -" convert your text into nice looking HTML. Its full markdown " -"documentation can be found\n" -" here.\n" -" An incomplete but most likely sufficient documentation can be found " -"below.\n" +" Markdown is lightweight markup language that can be used to format plain text easily.\n" +" This site uses the Python Markdown library to\n" +" convert your text into nice looking HTML. Its full markdown documentation can be found\n" +" here.\n" +" An incomplete but most likely sufficient documentation can be found below.\n" " " msgstr "" "\n" -"Markdown is een lichtgewicht opmaak taal die gebruikt kan worden om tekst " -"eenvoudig op te maken.\n" -"Deze site gebruikt de Python Markdown bibliotheek\n" -"om je tekst in mooi uitziende HTML om te zetten. De volledige documentatie " -"kan hiergevonden worden.\n" +"Markdown is een lichtgewicht opmaak taal die gebruikt kan worden om tekst eenvoudig op te maken.\n" +"Deze site gebruikt de Python Markdown bibliotheek\n" +"om je tekst in mooi uitziende HTML om te zetten. De volledige documentatie kan hiergevonden worden.\n" "Onvolledige, maar waarschijnlijk voldoende, informatie staat hieronder." #: .\cookbook\templates\markdown_info.html:25 @@ -1130,19 +1101,15 @@ msgid "Tables" msgstr "Tabellen" #: .\cookbook\templates\markdown_info.html:153 -#, fuzzy -#| msgid "" -#| "Markdown tables are hard to create by hand. It is recommended to use a " -#| "table editor like this one." msgid "" -"Markdown tables are hard to create by hand. It is recommended to use a table " -"editor like this one." +"Markdown tables are hard to create by hand. It is recommended to use a table" +" editor like this one." msgstr "" -"Het is lastig om markdown tabellen handmatig te creëren. Het is geadviseerd " -"dat u een tabel bewerker zoals deze gebruikt." +"Het is lastig om met de hand Markdown tabellen te maken. Het wordt " +"aangeraden om een tabel editor zoals deze te gebruiken." #: .\cookbook\templates\markdown_info.html:155 #: .\cookbook\templates\markdown_info.html:157 @@ -1180,18 +1147,18 @@ msgstr "Notitie (optioneel)" #: .\cookbook\templates\meal_plan.html:143 msgid "" -"You can use markdown to format this field. See the docs here" +"You can use markdown to format this field. See the docs " +"here" msgstr "" -"Je kan markdown gebruiken om dit veld op te maken. Zie de documentatie" +"Je kan markdown gebruiken om dit veld op te maken. Zie de documentatie" #: .\cookbook\templates\meal_plan.html:147 #: .\cookbook\templates\meal_plan.html:251 -#, fuzzy -#| msgid "Servings" msgid "Serving Count" -msgstr "Porties" +msgstr "Portie teller" #: .\cookbook\templates\meal_plan.html:153 msgid "Create only note" @@ -1226,8 +1193,8 @@ msgstr "Weekdag aanpassing" #: .\cookbook\templates\meal_plan.html:209 msgid "" -"Number of days starting from the first day of the week to offset the default " -"view." +"Number of days starting from the first day of the week to offset the default" +" view." msgstr "" "Aantal dagen startende met de eerste dag van de week om het standaard " "overzicht aan te passen." @@ -1269,94 +1236,37 @@ msgid "Meal Plan Help" msgstr "Maaltijdplanner hulp" #: .\cookbook\templates\meal_plan.html:344 -#, fuzzy -#| msgid "" -#| "\n" -#| "

The meal plan module allows planning of " -#| "meals both with recipes or just notes.

\n" -#| "

Simply select a recipe from the list of " -#| "recently viewed recipes or search the one you\n" -#| " want and drag it to the desired plan " -#| "position. You can also add a note and a title and\n" -#| " then drag the recipe to create a plan " -#| "entry with a custom title and note. Creating only\n" -#| " Notes is possible by dragging the create " -#| "note box into the plan.

\n" -#| "

Click on a recipe in order to open the " -#| "detail view. Here you can also add it to the\n" -#| " shopping list. You can also add all " -#| "recipes of a day to the shopping list by\n" -#| " clicking the shopping cart at the top of " -#| "the table.

\n" -#| "

Since a common use case is to plan meals " -#| "together you can define\n" -#| " users you want to share your plan with in " -#| "the settings.\n" -#| "

\n" -#| "

You can also edit the types of meals you " -#| "want to plan. If you share your plan with\n" -#| " someone with\n" -#| " different meals, their meal types will " -#| "appear in your list as well. To prevent\n" -#| " duplicates (e.g. Other and Misc.)\n" -#| " name your meal types the same as the " -#| "users you share your meals with and they will be\n" -#| " merged.

\n" -#| " " msgid "" "\n" -"

The meal plan module allows planning of meals " -"both with recipes and notes.

\n" -"

Simply select a recipe from the list of " -"recently viewed recipes or search the one you\n" -" want and drag it to the desired plan " -"position. You can also add a note and a title and\n" -" then drag the recipe to create a plan entry " -"with a custom title and note. Creating only\n" -" Notes is possible by dragging the create " -"note box into the plan.

\n" -"

Click on a recipe in order to open the " -"detailed view. There you can also add it to the\n" -" shopping list. You can also add all recipes " -"of a day to the shopping list by\n" -" clicking the shopping cart at the top of the " -"table.

\n" -"

Since a common use case is to plan meals " -"together you can define\n" -" users you want to share your plan with in " -"the settings.\n" +"

The meal plan module allows planning of meals both with recipes and notes.

\n" +"

Simply select a recipe from the list of recently viewed recipes or search the one you\n" +" want and drag it to the desired plan position. You can also add a note and a title and\n" +" then drag the recipe to create a plan entry with a custom title and note. Creating only\n" +" Notes is possible by dragging the create note box into the plan.

\n" +"

Click on a recipe in order to open the detailed view. There you can also add it to the\n" +" shopping list. You can also add all recipes of a day to the shopping list by\n" +" clicking the shopping cart at the top of the table.

\n" +"

Since a common use case is to plan meals together you can define\n" +" users you want to share your plan with in the settings.\n" "

\n" -"

You can also edit the types of meals you want " -"to plan. If you share your plan with\n" +"

You can also edit the types of meals you want to plan. If you share your plan with\n" " someone with\n" -" different meals, their meal types will " -"appear in your list as well. To prevent\n" +" different meals, their meal types will appear in your list as well. To prevent\n" " duplicates (e.g. Other and Misc.)\n" -" name your meal types the same as the users " -"you share your meals with and they will be\n" +" name your meal types the same as the users you share your meals with and they will be\n" " merged.

\n" " " msgstr "" "\n" -"

De maaltijdplanner maakt het mogelijk maaltijden op basis van recepten of " -"notities te plannen.

\n" -"

Selecteer een recept uit de lijst van recent bekeken recepten of zoek het " -"recept dat je wil en sleep het naar de gewenste positie. Je kan ook eerst " -"een notitie en titel toevoegen en dan het recept naar de gewenste positie " -"slepen om een maaltijdplan met een aangepaste titel en notitie te maken. " -"Alleen notities aanmaken is ook mogelijk door 'Maak notitie' in het " -"maaltijdplan te slepen.

\n" -"

Klik op een recept om het te openen en de details te bekijken. Hier kan " -"je het ook aan de boodschappenlijst toevoegen door op het winkelwagentje " -"bovenaan de tabel te klikken.

\n" -"

Omdat maaltijden vaak gezamenlijk worden gepland kan je in de " -"instellingen gebruikers aangeven met wie je het maaltijdplan wil delen.

\n" -"

Je kan ook de soort maaltijden die je wil plannen bewerken. Als je jouw " -"plan deelt met iemand met andere soorten, dan zullen deze ook in jouw lijst " -"verschijnen. Gelijknamige soorten worden samengevoegd. Zorg er daarom voor " -"dat de gebruikte soorten overeenkomen met de gebruiker met wie je je " -"maaltijdplannen deelt. Dit voorkomt dubbelingen (zoals Overige en " -"Willekeurig).

" +"

De maaltijdplan module maakt plannen van maaltijden met recepten en notities mogelijk.

\n" +"

Selecteer een recept van de lijst recent bekeken recepten of zoek naar\n" +"het gewenste recept en sleep het naar de juiste positie in het maaltijdplan. Je kan ook eerst een notitie en titel toevoegen en dan het recept naar de juiste positie slepen om een unieke maaltijdplan inschrijving te maken.\n" +"Alleen notities aanmaken is mogelijk door het Maak notitie vlak in het maaltijdplan te slepen.

\n" +"

Klik op een recept om de gedetailleerde weergave te openen. Daar kan je het ook toevoegen aan je boodschappenlijst.\n" +"Je kan ook alle recepten van een dag aan je boodschappenlijst toevoegen door op het winkelwagentje boven aan de tabel te klikken.

\n" +"

Omdat maaltijden samen gepland kunnen worden kan je in de instellingen kiezen met welke gebruikers je je maaltijd plan wil delen.\n" +"

\n" +"

Je kan ook het type maaltijd dat je wil plannen bewerken. Als je een maaltijdplan deelt met iemand met andere maaltijden, dan zullen hun maaltijdtypes ook in jouw lijst verschijnen. Geef, om dubbelingen (zoals Overig en Anders) te voorkomen, je maaltijdtypes daarom dezelfde naam als de gebruikers waarmee je maaltijdplannen deelt. In dat geval worden de maaltijden samengevoegd.

" #: .\cookbook\templates\meal_plan_entry.html:6 msgid "Meal Plan View" @@ -1373,27 +1283,31 @@ msgstr "Andere maaltijden op deze dag" #: .\cookbook\templates\no_groups_info.html:5 #: .\cookbook\templates\offline.html:6 msgid "Offline" -msgstr "" +msgstr "Offline" #: .\cookbook\templates\no_groups_info.html:12 msgid "No Permissions" -msgstr "" +msgstr "Geen rechten" #: .\cookbook\templates\no_groups_info.html:15 msgid "" "You do not have any groups and therefor cannot use this application. Please " "contact your administrator." msgstr "" +"Je hebt geen groepen en kan daarom deze applicatie niet gebruiken. Neem " +"contact op met je beheerder." #: .\cookbook\templates\offline.html:19 msgid "You are currently offline!" -msgstr "" +msgstr "Je bent op dit moment offline!" #: .\cookbook\templates\offline.html:20 msgid "" "The recipes listed below are available for offline viewing because you have " "recently viewed them. Keep in mind that data might be outdated." msgstr "" +"De recepten hieronder zijn beschikbaar om offline te bekijken omdat je ze " +"recent bekeken hebt. Houd er rekening mee dat de data mogelijk verouderd is." #: .\cookbook\templates\recipe_view.html:21 .\cookbook\templates\stats.html:47 msgid "Comments" @@ -1438,7 +1352,7 @@ msgstr "Account" #: .\cookbook\templates\settings.html:38 msgid "Link social account" -msgstr "" +msgstr "Koppel account socials" #: .\cookbook\templates\settings.html:42 msgid "Language" @@ -1462,8 +1376,8 @@ msgstr "" #: .\cookbook\templates\settings.html:92 msgid "" -"Use the token as an Authorization header prefixed by the word token as shown " -"in the following examples:" +"Use the token as an Authorization header prefixed by the word token as shown" +" in the following examples:" msgstr "" "Gebruik de token als een 'Authorization header'voorafgegaan door het woord " "token zoals in de volgende voorbeelden:" @@ -1484,7 +1398,8 @@ msgstr "Setup" msgid "" "To start using this application you must first create a superuser account." msgstr "" -"Om te starten met de applicatie moet je eerst een superuser account aanmaken." +"Om te starten met de applicatie moet je eerst een superuser account " +"aanmaken." #: .\cookbook\templates\setup.html:20 msgid "Create Superuser account" @@ -1500,13 +1415,11 @@ msgstr "Geen recepten geselecteerd" #: .\cookbook\templates\shopping_list.html:145 msgid "Entry Mode" -msgstr "" +msgstr "Invoermodus" #: .\cookbook\templates\shopping_list.html:153 -#, fuzzy -#| msgid "New Entry" msgid "Add Entry" -msgstr "Nieuw item" +msgstr "Zet op lijst" #: .\cookbook\templates\shopping_list.html:168 msgid "Amount" @@ -1514,13 +1427,11 @@ msgstr "Hoeveelheid" #: .\cookbook\templates\shopping_list.html:224 msgid "Supermarket" -msgstr "" +msgstr "Supermarkt" #: .\cookbook\templates\shopping_list.html:234 -#, fuzzy -#| msgid "Select User" msgid "Select Supermarket" -msgstr "Selecteer gebruiker" +msgstr "Selecteer supermarkt" #: .\cookbook\templates\shopping_list.html:258 msgid "Select User" @@ -1549,26 +1460,28 @@ msgstr "Er is een fout opgetreden bij het maken van een hulpbron!" #: .\cookbook\templates\socialaccount\connections.html:4 #: .\cookbook\templates\socialaccount\connections.html:7 msgid "Account Connections" -msgstr "" +msgstr "Account verbindingen" #: .\cookbook\templates\socialaccount\connections.html:10 msgid "" "You can sign in to your account using any of the following third party\n" " accounts:" msgstr "" +"Je kan inloggen met een account van een van de onderstaande derde partijen:" #: .\cookbook\templates\socialaccount\connections.html:36 msgid "Remove" -msgstr "" +msgstr "Verwijder" #: .\cookbook\templates\socialaccount\connections.html:44 msgid "" "You currently have no social network accounts connected to this account." msgstr "" +"Je hebt op dit moment geen sociaalnetwerk account aan dit account gekoppeld." #: .\cookbook\templates\socialaccount\connections.html:47 msgid "Add a 3rd Party Account" -msgstr "" +msgstr "Voeg account van een 3e partij toe" #: .\cookbook\templates\stats.html:4 msgid "Stats" @@ -1621,19 +1534,15 @@ msgstr "Systeeminformatie" #: .\cookbook\templates\system.html:51 msgid "" "\n" -" Django Recipes is an open source free software application. It can " -"be found on\n" +" Django Recipes is an open source free software application. It can be found on\n" " GitHub.\n" -" Changelogs can be found here.\n" +" Changelogs can be found here.\n" " " msgstr "" "\n" -"Django Recipes is een open source gratis software applicatie. Het kan " -"gevonden worden op\n" +"Django Recipes is een open source gratis software applicatie. Het kan gevonden worden op\n" "GitHub.\n" -"Wijzigingenoverzichten kunnen hier gevonden worden." +"Wijzigingenoverzichten kunnen hier gevonden worden." #: .\cookbook\templates\system.html:65 msgid "Media Serving" @@ -1653,15 +1562,12 @@ msgstr "Ok" msgid "" "Serving media files directly using gunicorn/python is not recommend!\n" " Please follow the steps described\n" -" here to update\n" +" here to update\n" " your installation.\n" " " msgstr "" -"Mediabestanden rechtstreeks aanbieden met gunicorn/python is niet " -"aanbevolen!\n" -"Volg de stappen zoals hier beschreven om je installatie te updaten." +"Mediabestanden rechtstreeks aanbieden met gunicorn/python is niet aanbevolen!\n" +"Volg de stappen zoals hier beschreven om je installatie te updaten." #: .\cookbook\templates\system.html:74 .\cookbook\templates\system.html:90 #: .\cookbook\templates\system.html:105 .\cookbook\templates\system.html:119 @@ -1675,20 +1581,15 @@ msgstr "Geheime sleutel" #: .\cookbook\templates\system.html:83 msgid "" "\n" -" You do not have a SECRET_KEY configured in your " -".env file. Django defaulted to the\n" +" You do not have a SECRET_KEY configured in your .env file. Django defaulted to the\n" " standard key\n" -" provided with the installation which is publicly know and " -"insecure! Please set\n" -" SECRET_KEY int the .env configuration " -"file.\n" +" provided with the installation which is publicly know and insecure! Please set\n" +" SECRET_KEY int the .env configuration file.\n" " " msgstr "" "\n" "Je hebt geen SECRET_KEY geconfigureerd in je .env bestand.\n" -"Django is overgegaan naar de standaard sleutel die openbaar en onveilig is! " -"Stel alsjeblieft SECRET_KEYin in het .env " -"configuratiebestand." +"Django is overgegaan naar de standaard sleutel die openbaar en onveilig is! Stel alsjeblieft SECRET_KEYin in het .env configuratiebestand." #: .\cookbook\templates\system.html:95 msgid "Debug Mode" @@ -1697,17 +1598,13 @@ msgstr "Debug modus" #: .\cookbook\templates\system.html:99 msgid "" "\n" -" This application is still running in debug mode. This is most " -"likely not needed. Turn of debug mode by\n" +" This application is still running in debug mode. This is most likely not needed. Turn of debug mode by\n" " setting\n" -" DEBUG=0 int the .env configuration " -"file.\n" +" DEBUG=0 int the .env configuration file.\n" " " msgstr "" "\n" -"Deze applicatie draait in debug modus. Dit is waarschijnlijk niet nodig. " -"Schakel debug modus uit door de instelling DEBUG=0 in het " -".envconfiguratiebestand aan te passen." +"Deze applicatie draait in debug modus. Dit is waarschijnlijk niet nodig. Schakel debug modus uit door de instelling DEBUG=0 in het .envconfiguratiebestand aan te passen." #: .\cookbook\templates\system.html:110 msgid "Database" @@ -1720,15 +1617,12 @@ msgstr "Info" #: .\cookbook\templates\system.html:114 msgid "" "\n" -" This application is not running with a Postgres database " -"backend. This is ok but not recommended as some\n" +" This application is not running with a Postgres database backend. This is ok but not recommended as some\n" " features only work with postgres databases.\n" " " msgstr "" "\n" -"Deze applicatie draait niet met een Postgres database als backend. Dit is ok " -"maar wordt niet aanbevolen omdat sommige functies alleen werken met Postgres " -"databases." +"Deze applicatie draait niet met een Postgres database als backend. Dit is ok maar wordt niet aanbevolen omdat sommige functies alleen werken met Postgres databases." #: .\cookbook\templates\url_import.html:5 msgid "URL Import" @@ -1763,18 +1657,16 @@ msgstr "Informatie" #: .\cookbook\templates\url_import.html:235 msgid "" " Only websites containing ld+json or microdata information can currently\n" -" be imported. Most big recipe pages " -"support this. If you site cannot be imported but\n" +" be imported. Most big recipe pages support this. If you site cannot be imported but\n" " you think\n" -" it probably has some kind of structured " -"data feel free to post an example in the\n" +" it probably has some kind of structured data feel free to post an example in the\n" " github issues." msgstr "" "Alleen websites die Id+json of microdata informatie bevatten kunnen op dit " "moment geïmporteerd worden. De meeste grote recepten websites ondersteunen " "dit. Als jouw website niet geïmporteerd kan worden maar je denkt dat het " -"waarschijnlijk gestructureerde data bevat, voel je dan vrij om een foorbeeld " -"te posten in de GitHub issues." +"waarschijnlijk gestructureerde data bevat, voel je dan vrij om een foorbeeld" +" te posten in de GitHub issues." #: .\cookbook\templates\url_import.html:243 msgid "Google ld+json Info" @@ -1798,7 +1690,7 @@ msgstr "Voorkeur voor gebruiker bestaat al" #: .\cookbook\views\api.py:416 .\cookbook\views\views.py:265 msgid "This feature is not available in the demo version!" -msgstr "" +msgstr "Deze optie is niet beschikbaar in de demo versie!" #: .\cookbook\views\api.py:439 msgid "Sync successful!" @@ -1888,7 +1780,7 @@ msgstr "Eenheden samengevoegd!" #: .\cookbook\views\edit.py:295 .\cookbook\views\edit.py:317 msgid "Cannot merge with the same object!" -msgstr "" +msgstr "Kan niet met hetzelfde object samenvoegen!" #: .\cookbook\views\edit.py:311 msgid "Foods merged!" @@ -1896,11 +1788,11 @@ msgstr "Ingrediënten samengevoegd!" #: .\cookbook\views\import_export.py:42 msgid "Importing is not implemented for this provider" -msgstr "" +msgstr "Importeren is voor deze provider niet geïmplementeerd" #: .\cookbook\views\import_export.py:58 msgid "Exporting is not implemented for this provider" -msgstr "" +msgstr "Exporteren is voor deze provider niet geïmplementeerd" #: .\cookbook\views\lists.py:42 msgid "Import Log" @@ -1932,7 +1824,7 @@ msgstr "Opmerking opgeslagen!" #: .\cookbook\views\views.py:152 msgid "This recipe is already linked to the book!" -msgstr "" +msgstr "Dit recept is al aan het boek gekoppeld!" #: .\cookbook\views\views.py:158 msgid "Bookmark saved!" @@ -1941,8 +1833,8 @@ msgstr "Bladwijzer opgeslagen!" #: .\cookbook\views\views.py:380 msgid "" "The setup page can only be used to create the first user! If you have " -"forgotten your superuser credentials please consult the django documentation " -"on how to reset passwords." +"forgotten your superuser credentials please consult the django documentation" +" on how to reset passwords." msgstr "" "De setup pagina kan alleen gebruikt worden om de eerste gebruiker aan te " "maken! Indien je je superuser inloggegevens bent vergeten zal je de django " @@ -1964,150 +1856,3 @@ msgstr "Onjuiste uitnodigingslink opgegeven!" #: .\cookbook\views\views.py:470 msgid "Invite Link not valid or already used!" msgstr "De uitnodigingslink is niet valide of al gebruikt!" - -#~ msgid "Export Base64 encoded image?" -#~ msgstr "Base64-gecodeerde afbeelding exporteren?" - -#~ msgid "Download export directly or show on page?" -#~ msgstr "De export direct downloaden of op de pagina weergeven?" - -#~ msgid "Simply paste a JSON export into this textarea and click import." -#~ msgstr "Plak een JSON export in dit tekstveld en klik op importeren." - -#~ msgid "Scaling factor for recipe." -#~ msgstr "Schaalfactor voor recept." - -#~ msgid "Exported Recipe" -#~ msgstr "Geëxporteerd recept" - -#~ msgid "Copy to clipboard" -#~ msgstr "Naar het klembord kopiëren" - -#~ msgid "Copied!" -#~ msgstr "Gekopieerd!" - -#~ msgid "Copy list to clipboard" -#~ msgstr "Lijst naar het klembord kopiëren" - -#~ msgid "Error" -#~ msgstr "Error" - -#~ msgid "There was an error loading the recipe!" -#~ msgstr "Er is een fout opgetreden bij het laden van het recept!" - -#~ msgid "Updated" -#~ msgstr "Geüpdatet" - -#~ msgid "Changes saved successfully!" -#~ msgstr "Wijzigingen succesvol opgeslagen!" - -#~ msgid "There was an error updating the recipe!" -#~ msgstr "Er is een fout opgetreden bij het updaten van het recept!" - -#~ msgid "Are you sure that you want to delete this ingredient?" -#~ msgstr "Weet je zeker dat je dit ingrediënt wil verwijderen?" - -#~ msgid "Are you sure that you want to delete this step?" -#~ msgstr "Weet je zeker dat je deze stap wil verwijderen?" - -#~ msgid "There was an error loading a resource!" -#~ msgstr "Er is een fout opgetreden bij het laden van een hulpbron!" - -#~ msgid "Recipe Multiplier" -#~ msgstr "Recept vermenigvuldiger" - -#~ msgid "" -#~ "When deleting a meal type all entries using that type will be deleted as " -#~ "well. Deletion will apply when configuration is saved. Do you want to " -#~ "proceed?" -#~ msgstr "" -#~ "Bij het verwijderen van een maaltijdsoort worden alle inzendingen die de " -#~ "maaltijdsoort gebruikt verwijderd. Verwijdering vindt plaats wanneer de " -#~ "configuratie opgeslagen wordt. Wil je doorgaan?" - -#~ msgid "Add to Book" -#~ msgstr "Aan Boek toevoegen" - -#~ msgid "Add to Plan" -#~ msgstr "Aan Plan toevoegen" - -#~ msgid "Print" -#~ msgstr "Printen" - -#~ msgid "Share" -#~ msgstr "Deel" - -#~ msgid "in" -#~ msgstr "binnen" - -#~ msgid "Preparation time ~" -#~ msgstr "Bereidingstijd" - -#~ msgid "Minutes" -#~ msgstr "Minuten" - -#~ msgid "View external recipe" -#~ msgstr "Extern recept bekijken" - -#~ msgid "External recipe image" -#~ msgstr "Externe recept afbeelding" - -#~ msgid "External recipe" -#~ msgstr "Extern recept" - -#~ msgid "" -#~ "\n" -#~ " This is an external recipe, which " -#~ "means you can only view it by opening the link\n" -#~ " above.\n" -#~ " You can convert this recipe to a " -#~ "fancy recipe by pressing the convert button. The\n" -#~ " original\n" -#~ " file\n" -#~ " will still be accessible.\n" -#~ " " -#~ msgstr "" -#~ "\n" -#~ "Dit is een extern recept, dat betekent dat je het dient te openen met de " -#~ "bovenstaande link.\n" -#~ "Je kan dit recept naar een flitsend recept omzetten door op de converteer " -#~ "knop te klikken.\n" -#~ "Het originele bestand blijft beschikbaar." - -#~ msgid "Convert now!" -#~ msgstr "Nu converteren" - -#~ msgid "Your username and password didn't match. Please try again." -#~ msgstr "" -#~ "Je gebruikersnaam en wachtwoord komen niet overeen. Probeer het opnieuw." - -#~ msgid "There was an error updating a resource!" -#~ msgstr "Er is een fout opgetreden bij het updaten van een hulpbron!" - -#~ msgid "Object created successfully!" -#~ msgstr "Object succesvol aangemaakt!" - -#~ msgid "Please enter a valid food" -#~ msgstr "Geef een geldig ingrediënt op" - -#~ msgid "Already importing the selected recipe, please wait!" -#~ msgstr "Het geselecteerde recept wordt geïmporteerd, even geduld!" - -#~ msgid "An error occurred while trying to import this recipe!" -#~ msgstr "Er is een error opgetreden bij het importeren van dit recept!" - -#~ msgid "Recipe imported successfully!" -#~ msgstr "Recept succesvol geïmporteerd!" - -#~ msgid "Something went wrong during the import!" -#~ msgstr "Er is iets misgegaan tijdens het importeren!" - -#~ msgid "Could not parse the supplied JSON!" -#~ msgstr "Er zit een fout in de opgegeven JSON!" - -#~ msgid "" -#~ "External recipes cannot be exported, please share the file directly or " -#~ "select an internal recipe." -#~ msgstr "" -#~ "Het is niet mogelijk om externe recepten te exporteren. Deel het bestand " -#~ "zelf of selecteer een intern recept." From c99c944130109f7c5fcda845aa0af3fcbada432b Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 25 Feb 2021 22:19:51 +0100 Subject: [PATCH 42/96] fixed normal django test running with scopes --- cookbook/helper/CustomTestRunner.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 cookbook/helper/CustomTestRunner.py diff --git a/cookbook/helper/CustomTestRunner.py b/cookbook/helper/CustomTestRunner.py new file mode 100644 index 00000000..b7043051 --- /dev/null +++ b/cookbook/helper/CustomTestRunner.py @@ -0,0 +1,8 @@ +from django.test.runner import DiscoverRunner +from django_scopes import scopes_disabled + + +class CustomTestRunner(DiscoverRunner): + def run_tests(self, *args, **kwargs): + with scopes_disabled(): + return super().run_tests(*args, **kwargs) From 54e71f2910ed70dc892acda67c1ac112321cc44f Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 25 Feb 2021 22:20:06 +0100 Subject: [PATCH 43/96] last commit --- recipes/settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/recipes/settings.py b/recipes/settings.py index 9f12286b..a14c7c0d 100644 --- a/recipes/settings.py +++ b/recipes/settings.py @@ -241,3 +241,5 @@ MEDIA_ROOT = os.path.join(BASE_DIR, "mediafiles") # Serve static files with gzip STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' + +TEST_RUNNER = "cookbook.helper.CustomTestRunner.CustomTestRunner" From 5fd03e7cdced7c4f52a8ad319ffbbd56ada72e7e Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 25 Feb 2021 22:36:20 +0100 Subject: [PATCH 44/96] basics of pytest --- cookbook/tests/pytest/__init__.py | 6 ++++ cookbook/tests/pytest/conftest.py | 58 ++++++++++++++++++++++++++++++ cookbook/tests/pytest/test_test.py | 20 +++++++++++ pytest.ini | 3 ++ 4 files changed, 87 insertions(+) create mode 100644 cookbook/tests/pytest/__init__.py create mode 100644 cookbook/tests/pytest/conftest.py create mode 100644 cookbook/tests/pytest/test_test.py create mode 100644 pytest.ini diff --git a/cookbook/tests/pytest/__init__.py b/cookbook/tests/pytest/__init__.py new file mode 100644 index 00000000..255e8298 --- /dev/null +++ b/cookbook/tests/pytest/__init__.py @@ -0,0 +1,6 @@ +from django.test import utils +from django_scopes import scopes_disabled + +# disables scoping error in all queries used inside the test functions +# fixtures need to have their own scopes_disabled +utils.setup_databases = scopes_disabled()(utils.setup_databases) diff --git a/cookbook/tests/pytest/conftest.py b/cookbook/tests/pytest/conftest.py new file mode 100644 index 00000000..d5d9bc96 --- /dev/null +++ b/cookbook/tests/pytest/conftest.py @@ -0,0 +1,58 @@ +import inspect +import uuid + +import pytest +from django.contrib.auth.models import User, Group +from django_scopes import scopes_disabled + +from cookbook.models import Space + + +@pytest.fixture +def test_password(): + return 'strong-test-pass' + + +@pytest.fixture +def create_user(db, django_user_model, test_password): + def make_user(**kwargs): + kwargs['password'] = test_password + if 'username' not in kwargs: + kwargs['username'] = str(uuid.uuid4()) + return django_user_model.objects.create_user(**kwargs) + + return make_user + + +@pytest.fixture +def space_1(client): + with scopes_disabled(): + return Space.objects.get_or_create(name='space_1')[0] + + +@pytest.fixture +def space_2(client): + with scopes_disabled(): + return Space.objects.get_or_create(name='space_2')[0] + + +@pytest.fixture +def user_1(client, space_1): + with scopes_disabled(): + user = User.objects.create(username='user_1') + user.groups.add(Group.objects.get(name='user')) + user.userpreference.space = space_1 + user.userpreference.save() + client.force_login(user) + return client + + +@pytest.fixture +def user_2(client, space_2): + with scopes_disabled(): + user = User.objects.create(username='user_2') + user.groups.add(Group.objects.get(name='user')) + user.userpreference.space = space_2 + user.userpreference.save() + client.force_login(user) + return client diff --git a/cookbook/tests/pytest/test_test.py b/cookbook/tests/pytest/test_test.py new file mode 100644 index 00000000..e9ec9586 --- /dev/null +++ b/cookbook/tests/pytest/test_test.py @@ -0,0 +1,20 @@ +import json + +import pytest + +from django.contrib.auth.models import User +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import Keyword, Space + + +@pytest.mark.django_db +def test_user_create(user_1, user_2): + r = user_1.post(reverse('api:keyword-list'), {'name': 'test', 'space': 1}, content_type='application/json') + response = json.loads(r.content) + assert r.status_code == 201 + assert response['name'] == 'test' + + r = user_2.get(reverse('api:keyword-detail', args={response['id']}), content_type='application/json') + assert r.status_code == 404 diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..79e7a4e2 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +DJANGO_SETTINGS_MODULE = recipes.settings +python_files = tests.py test_*.py *_tests.py From b6acc17e5a94cda90bd0b313c09263b91966c041 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Fri, 26 Feb 2021 10:02:14 +0100 Subject: [PATCH 45/96] Create url_import.md --- .github/ISSUE_TEMPLATE/url_import.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/url_import.md diff --git a/.github/ISSUE_TEMPLATE/url_import.md b/.github/ISSUE_TEMPLATE/url_import.md new file mode 100644 index 00000000..c99115a1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/url_import.md @@ -0,0 +1,22 @@ +--- +name: Website Import +about: Anything related to website imports +title: '' +labels: enhancement, url_import +assignees: '' + +--- + +### Version +Please provide your current version (can be found on the system page since v0.8.4) +Version: + +### Information +Exact URL you are trying to import from: + +When did the issue happen: When pressing the search button with the url / when importing after the page has loaded + +Response/Message shown +``` +Message +``` From 323f4246308693f098fe21f91b836d7d29cc2973 Mon Sep 17 00:00:00 2001 From: Oliver Cervera Date: Sat, 6 Mar 2021 13:03:03 +0100 Subject: [PATCH 46/96] Update Italian Translation Italian translation updates. Manual PR since Transifex doesn't do it. --- cookbook/locale/it/LC_MESSAGES/django.po | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/cookbook/locale/it/LC_MESSAGES/django.po b/cookbook/locale/it/LC_MESSAGES/django.po index ed945656..c603e02f 100644 --- a/cookbook/locale/it/LC_MESSAGES/django.po +++ b/cookbook/locale/it/LC_MESSAGES/django.po @@ -235,11 +235,11 @@ msgstr "" #: .\cookbook\helper\permission_helper.py:242 .\cookbook\views\data.py:32 #: .\cookbook\views\views.py:106 .\cookbook\views\views.py:218 msgid "You do not have the required permissions to view this page!" -msgstr "Non hai i permessi richiesti per visualizzare questa pagina!" +msgstr "Non hai i permessi necessari per visualizzare questa pagina!" #: .\cookbook\helper\permission_helper.py:151 msgid "You are not logged in and therefore cannot view this page!" -msgstr "Non sei loggato e quindi non puoi visualizzare questa pagina!" +msgstr "Non hai fatto l'accesso e quindi non puoi visualizzare questa pagina!" #: .\cookbook\helper\permission_helper.py:161 #: .\cookbook\helper\permission_helper.py:177 @@ -282,7 +282,7 @@ msgstr "Porzioni" #: .\cookbook\integration\safron.py:25 msgid "Waiting time" -msgstr "Tempo di attesa" +msgstr "Tempo di cottura" #: .\cookbook\integration\safron.py:27 #: .\cookbook\templates\forms\edit_internal_recipe.html:59 @@ -456,7 +456,7 @@ msgstr "Parola chiave" #: .\cookbook\templates\base.html:100 msgid "Batch Edit" -msgstr "Modifica di massa" +msgstr "Modifica in blocco" #: .\cookbook\templates\base.html:105 msgid "Storage Data" @@ -526,17 +526,17 @@ msgstr "Logout" #: .\cookbook\templates\batch\edit.html:6 msgid "Batch edit Category" -msgstr "Modifica di massa per categoria" +msgstr "Modifica in blocco per categoria" #: .\cookbook\templates\batch\edit.html:15 msgid "Batch edit Recipes" -msgstr "Modifica di massa per ricette" +msgstr "Modifica in blocco per ricette" #: .\cookbook\templates\batch\edit.html:20 msgid "Add the specified keywords to all recipes containing a word" msgstr "" -"Aggiungi a tutte le ricette che contengono una determinata stringa le parole" -" chiave desiderate " +"Aggiungi le parole chiave che desideri a tutte le ricette che contengono una" +" determinata stringa" #: .\cookbook\templates\batch\monitor.html:6 .\cookbook\views\edit.py:66 msgid "Sync" @@ -556,7 +556,7 @@ msgstr "" #: .\cookbook\templates\batch\monitor.html:16 msgid "The path must be in the following format" -msgstr "Il path deve essere nel formato seguente" +msgstr "Il percorso deve essere nel formato seguente" #: .\cookbook\templates\batch\monitor.html:27 msgid "Sync Now!" @@ -636,7 +636,7 @@ msgstr "Modifica Ricetta" #: .\cookbook\templates\forms\edit_internal_recipe.html:62 msgid "Waiting Time" -msgstr "Tempo di Attesa" +msgstr "Tempo di cottura" #: .\cookbook\templates\forms\edit_internal_recipe.html:68 msgid "Servings Text" @@ -1148,7 +1148,7 @@ msgstr "Titolo" #: .\cookbook\templates\meal_plan.html:141 msgid "Note (optional)" -msgstr "Note (opzionale)" +msgstr "Nota (opzionale)" #: .\cookbook\templates\meal_plan.html:143 msgid "" @@ -1341,7 +1341,7 @@ msgstr "Tempo di preparazione circa" #: .\cookbook\templates\recipes_table.html:52 #: .\cookbook\templates\url_import.html:60 msgid "Waiting time ca." -msgstr "Tempo di attesa circa" +msgstr "Tempo di cottura circa" #: .\cookbook\templates\recipes_table.html:55 msgid "External" @@ -1726,7 +1726,7 @@ msgid_plural "Batch edit done. %(count)d Recipes where updated." msgstr[0] "" "Modifica di massa completata. %(count)d ricetta è stata aggiornata." msgstr[1] "" -"Modifica di massa completata. %(count)d ricette sono state aggiornate." +"Modifica in blocco completata. %(count)d ricette sono state aggiornate." #: .\cookbook\views\delete.py:72 msgid "Monitor" @@ -1829,7 +1829,7 @@ msgstr "Si è verificato un errore durante l'importazione di questa ricetta!" #: .\cookbook\views\views.py:117 msgid "You do not have the required permissions to perform this action!" -msgstr "Non hai i permessi necessari per effettuare questa operazione!" +msgstr "Non hai i permessi necessari per completare questa operazione!" #: .\cookbook\views\views.py:136 msgid "Comment saved!" From 4c03520371013c44f342b37e381100b0fbd20316 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Mar 2021 06:58:23 +0000 Subject: [PATCH 47/96] Bump pillow from 8.1.0 to 8.1.2 Bumps [pillow](https://github.com/python-pillow/Pillow) from 8.1.0 to 8.1.2. - [Release notes](https://github.com/python-pillow/Pillow/releases) - [Changelog](https://github.com/python-pillow/Pillow/blob/master/CHANGES.rst) - [Commits](https://github.com/python-pillow/Pillow/compare/8.1.0...8.1.2) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1e0e5120..00c86561 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,7 @@ drf-writable-nested==0.6.2 gunicorn==20.0.4 lxml==4.6.2 Markdown==3.3.4 -Pillow==8.1.0 +Pillow==8.1.2 psycopg2-binary==2.8.6 python-dotenv==0.15.0 requests==2.25.1 From ba4c3b95e55bde1c283ccd8eb2bf69fa10b534eb Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 10 Mar 2021 18:17:31 +0100 Subject: [PATCH 48/96] removed deprecated functions/packages --- cookbook/helper/template_helper.py | 2 +- cookbook/templatetags/custom_tags.py | 2 +- recipes/urls.py | 7 +++---- requirements.txt | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cookbook/helper/template_helper.py b/cookbook/helper/template_helper.py index f709dccc..4eb4b98c 100644 --- a/cookbook/helper/template_helper.py +++ b/cookbook/helper/template_helper.py @@ -1,6 +1,6 @@ import bleach import markdown as md -from bleach_whitelist import markdown_attrs, markdown_tags +from bleach_allowlist import markdown_attrs, markdown_tags from cookbook.helper.mdx_attributes import MarkdownFormatExtension from cookbook.helper.mdx_urlize import UrlizeExtension from jinja2 import Template, TemplateSyntaxError diff --git a/cookbook/templatetags/custom_tags.py b/cookbook/templatetags/custom_tags.py index 8e225c7a..7e1db00e 100644 --- a/cookbook/templatetags/custom_tags.py +++ b/cookbook/templatetags/custom_tags.py @@ -1,6 +1,6 @@ import bleach import markdown as md -from bleach_whitelist import markdown_attrs, markdown_tags +from bleach_allowlist import markdown_attrs, markdown_tags from cookbook.helper.mdx_attributes import MarkdownFormatExtension from cookbook.helper.mdx_urlize import UrlizeExtension from cookbook.models import Space, get_model_name diff --git a/recipes/urls.py b/recipes/urls.py index 0879fbcc..29af6332 100644 --- a/recipes/urls.py +++ b/recipes/urls.py @@ -15,9 +15,8 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.conf import settings -from django.conf.urls import url from django.contrib import admin -from django.urls import include, path +from django.urls import include, path, re_path from django.views.i18n import JavaScriptCatalog from django.views.static import serve from django_js_reverse import views as reverse_views @@ -35,5 +34,5 @@ urlpatterns = [ ] if settings.GUNICORN_MEDIA or settings.DEBUG: - urlpatterns += url(r'^media/(?P.*)$', serve, {'document_root': settings.MEDIA_ROOT}), - urlpatterns += url(r'^jsreverse.json$', reverse_views.urls_js, name='js_reverse'), + urlpatterns += re_path(r'^media/(?P.*)$', serve, {'document_root': settings.MEDIA_ROOT}), + urlpatterns += re_path(r'^jsreverse.json$', reverse_views.urls_js, name='js_reverse'), diff --git a/requirements.txt b/requirements.txt index a7488f62..f95c9893 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ bleach==3.3.0 -bleach-whitelist==0.0.11 +bleach-allowlist==1.0.3 Django==3.1.7 django-annoying==0.10.6 django-autocomplete-light==3.8.2 From 4742056223ac28d4c1c1a96cd8783cfdbc41d3a7 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 10 Mar 2021 18:18:19 +0100 Subject: [PATCH 49/96] tests basically working --- cookbook/tests/pytest/conftest.py | 22 ++++++++++++++++------ cookbook/tests/pytest/test_test.py | 7 ++++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/cookbook/tests/pytest/conftest.py b/cookbook/tests/pytest/conftest.py index d5d9bc96..a5eb380d 100644 --- a/cookbook/tests/pytest/conftest.py +++ b/cookbook/tests/pytest/conftest.py @@ -1,3 +1,4 @@ +import copy import inspect import uuid @@ -8,6 +9,11 @@ from django_scopes import scopes_disabled from cookbook.models import Space +@pytest.fixture(autouse=True) +def enable_db_access_for_all_tests(db): + pass + + @pytest.fixture def test_password(): return 'strong-test-pass' @@ -25,34 +31,38 @@ def create_user(db, django_user_model, test_password): @pytest.fixture -def space_1(client): +def space_1(): with scopes_disabled(): return Space.objects.get_or_create(name='space_1')[0] @pytest.fixture -def space_2(client): +def space_2(): with scopes_disabled(): return Space.objects.get_or_create(name='space_2')[0] @pytest.fixture def user_1(client, space_1): + c = copy.deepcopy(client) with scopes_disabled(): + print(f'creating user 1 with space {space_1}') user = User.objects.create(username='user_1') user.groups.add(Group.objects.get(name='user')) user.userpreference.space = space_1 user.userpreference.save() - client.force_login(user) - return client + c.force_login(user) + return c @pytest.fixture def user_2(client, space_2): + c = copy.deepcopy(client) with scopes_disabled(): + print(f'creating user 2 with space {space_2}') user = User.objects.create(username='user_2') user.groups.add(Group.objects.get(name='user')) user.userpreference.space = space_2 user.userpreference.save() - client.force_login(user) - return client + c.force_login(user) + return c diff --git a/cookbook/tests/pytest/test_test.py b/cookbook/tests/pytest/test_test.py index e9ec9586..0053cc74 100644 --- a/cookbook/tests/pytest/test_test.py +++ b/cookbook/tests/pytest/test_test.py @@ -10,11 +10,16 @@ from cookbook.models import Keyword, Space @pytest.mark.django_db -def test_user_create(user_1, user_2): +def test_user_create(user_2, user_1): r = user_1.post(reverse('api:keyword-list'), {'name': 'test', 'space': 1}, content_type='application/json') response = json.loads(r.content) assert r.status_code == 201 assert response['name'] == 'test' + print('DEEEEEBUUUUUGGGG') + print(user_1.get(reverse('view_test')).content) + print(user_2.get(reverse('view_test')).content) + print(user_2) + r = user_2.get(reverse('api:keyword-detail', args={response['id']}), content_type='application/json') assert r.status_code == 404 From b9b7a125f027ba0622bd84c80e6cf6615af9291e Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 10 Mar 2021 19:46:08 +0100 Subject: [PATCH 50/96] more tests working but scopes broken --- .idea/recipes.iml | 3 + cookbook/tests/api/test_api_keyword.py | 93 ------------- cookbook/tests/pytest/api/__init__.py | 6 + cookbook/tests/pytest/api/test_api_keyword.py | 94 +++++++++++++ cookbook/tests/pytest/conftest.py | 128 +++++++++++++----- cookbook/tests/pytest/test_test.py | 11 +- pytest.ini | 2 +- 7 files changed, 199 insertions(+), 138 deletions(-) delete mode 100644 cookbook/tests/api/test_api_keyword.py create mode 100644 cookbook/tests/pytest/api/__init__.py create mode 100644 cookbook/tests/pytest/api/test_api_keyword.py diff --git a/.idea/recipes.iml b/.idea/recipes.iml index c2b653f2..e1dd7064 100644 --- a/.idea/recipes.iml +++ b/.idea/recipes.iml @@ -29,4 +29,7 @@ + + \ No newline at end of file diff --git a/cookbook/tests/api/test_api_keyword.py b/cookbook/tests/api/test_api_keyword.py deleted file mode 100644 index 6e870f32..00000000 --- a/cookbook/tests/api/test_api_keyword.py +++ /dev/null @@ -1,93 +0,0 @@ -import json - -from cookbook.models import Keyword -from cookbook.tests.views.test_views import TestViews -from django.urls import reverse - -class TestApiKeyword(TestViews): - - def setUp(self): - super(TestApiKeyword, self).setUp() - self.keyword_1 = Keyword.objects.create( - name='meat' - ) - self.keyword_2 = Keyword.objects.create( - name='veggies' - ) - - def test_keyword_list(self): - # verify view permissions are applied accordingly - self.batch_requests( - [ - (self.anonymous_client, 403), - (self.guest_client_1, 403), - (self.user_client_1, 200), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - reverse('api:keyword-list') - ) - - # verify storage is returned - r = self.user_client_1.get(reverse('api:keyword-list')) - self.assertEqual(r.status_code, 200) - response = json.loads(r.content) - self.assertEqual(len(response), 2) - self.assertEqual(response[0]['name'], self.keyword_1.name) - - r = self.user_client_1.get(f'{reverse("api:keyword-list")}?limit=1') - response = json.loads(r.content) - self.assertEqual(len(response), 1) - - r = self.user_client_1.get( - f'{reverse("api:keyword-list")}?query=chicken' - ) - response = json.loads(r.content) - self.assertEqual(len(response), 0) - - r = self.user_client_1.get(f'{reverse("api:keyword-list")}?query=MEAT') - response = json.loads(r.content) - self.assertEqual(len(response), 1) - - def test_keyword_update(self): - r = self.user_client_1.patch( - reverse( - 'api:keyword-detail', - args={self.keyword_1.id} - ), - {'name': 'new'}, - content_type='application/json' - ) - response = json.loads(r.content) - self.assertEqual(r.status_code, 200) - self.assertEqual(response['name'], 'new') - - def test_keyword_add(self): - r = self.user_client_1.post( - reverse('api:keyword-list'), - {'name': 'test'}, - content_type='application/json' - ) - response = json.loads(r.content) - self.assertEqual(r.status_code, 201) - self.assertEqual(response['name'], 'test') - - def test_keyword_add_duplicate(self): - r = self.user_client_1.post( - reverse('api:keyword-list'), - {'name': self.keyword_1.name}, - content_type='application/json' - ) - response = json.loads(r.content) - self.assertEqual(r.status_code, 201) - self.assertEqual(response['name'], self.keyword_1.name) - - def test_keyword_delete(self): - r = self.user_client_1.delete( - reverse( - 'api:keyword-detail', - args={self.keyword_1.id} - ) - ) - self.assertEqual(r.status_code, 204) - self.assertEqual(Keyword.objects.count(), 1) diff --git a/cookbook/tests/pytest/api/__init__.py b/cookbook/tests/pytest/api/__init__.py new file mode 100644 index 00000000..255e8298 --- /dev/null +++ b/cookbook/tests/pytest/api/__init__.py @@ -0,0 +1,6 @@ +from django.test import utils +from django_scopes import scopes_disabled + +# disables scoping error in all queries used inside the test functions +# fixtures need to have their own scopes_disabled +utils.setup_databases = scopes_disabled()(utils.setup_databases) diff --git a/cookbook/tests/pytest/api/test_api_keyword.py b/cookbook/tests/pytest/api/test_api_keyword.py new file mode 100644 index 00000000..6f7656ee --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_keyword.py @@ -0,0 +1,94 @@ +import json + +import pytest +from django_scopes import scopes_disabled + +from cookbook.models import Keyword +from cookbook.tests.views.test_views import TestViews +from django.urls import reverse + + +@pytest.fixture() +def keyword_1(): + return Keyword.objects.get_or_create(name='test_1')[0] + + +@pytest.fixture +def keyword_2(): + return Keyword.objects.get_or_create(name='test_2')[0] + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('api:keyword-list')).status_code == arg[1] + + +def test_list_filter(keyword_1, keyword_2, u1_s1): + # verify storage is returned + r = u1_s1.get(reverse('api:keyword-list')) + assert r.status_code == 200 + response = json.loads(r.content) + assert len(response) == 2 + assert response[0]['name'] == keyword_1.name + + response = json.loads(u1_s1.get(f'{reverse("api:keyword-list")}?limit=1')) + assert len(response) == 1 + + response = json.loads(u1_s1.get(f'{reverse("api:keyword-list")}?query=chicken')) + assert len(response) == 0 + + response = json.loads(u1_s1.get(f'{reverse("api:keyword-list")}?query={keyword_1.name[4:]}')) + assert len(response) == 1 + +# +# def test_keyword_update(self): +# r = self.user_client_1.patch( +# reverse( +# 'api:keyword-detail', +# args={self.keyword_1.id} +# ), +# {'name': 'new'}, +# content_type='application/json' +# ) +# response = json.loads(r.content) +# self.assertEqual(r.status_code, 200) +# self.assertEqual(response['name'], 'new') +# +# +# def test_keyword_add(self): +# r = self.user_client_1.post( +# reverse('api:keyword-list'), +# {'name': 'test'}, +# content_type='application/json' +# ) +# response = json.loads(r.content) +# self.assertEqual(r.status_code, 201) +# self.assertEqual(response['name'], 'test') +# +# +# def test_keyword_add_duplicate(self): +# r = self.user_client_1.post( +# reverse('api:keyword-list'), +# {'name': self.keyword_1.name}, +# content_type='application/json' +# ) +# response = json.loads(r.content) +# self.assertEqual(r.status_code, 201) +# self.assertEqual(response['name'], self.keyword_1.name) +# +# +# def test_keyword_delete(self): +# r = self.user_client_1.delete( +# reverse( +# 'api:keyword-detail', +# args={self.keyword_1.id} +# ) +# ) +# self.assertEqual(r.status_code, 204) +# self.assertEqual(Keyword.objects.count(), 1) diff --git a/cookbook/tests/pytest/conftest.py b/cookbook/tests/pytest/conftest.py index a5eb380d..a424b583 100644 --- a/cookbook/tests/pytest/conftest.py +++ b/cookbook/tests/pytest/conftest.py @@ -1,5 +1,4 @@ import copy -import inspect import uuid import pytest @@ -14,55 +13,112 @@ def enable_db_access_for_all_tests(db): pass -@pytest.fixture -def test_password(): - return 'strong-test-pass' - - -@pytest.fixture -def create_user(db, django_user_model, test_password): - def make_user(**kwargs): - kwargs['password'] = test_password - if 'username' not in kwargs: - kwargs['username'] = str(uuid.uuid4()) - return django_user_model.objects.create_user(**kwargs) - - return make_user - - -@pytest.fixture +@pytest.fixture() def space_1(): with scopes_disabled(): return Space.objects.get_or_create(name='space_1')[0] -@pytest.fixture +@pytest.fixture() def space_2(): with scopes_disabled(): return Space.objects.get_or_create(name='space_2')[0] -@pytest.fixture -def user_1(client, space_1): +# ---------------------- USER FIXTURES ----------------------- +# maybe better with factories but this is very explict so ... + +def create_user(client, space, **kwargs): c = copy.deepcopy(client) with scopes_disabled(): - print(f'creating user 1 with space {space_1}') - user = User.objects.create(username='user_1') - user.groups.add(Group.objects.get(name='user')) - user.userpreference.space = space_1 + group = kwargs.pop('group', None) + username = kwargs.pop('username', uuid.uuid4()) + + user = User.objects.create(username=username, **kwargs) + if group: + user.groups.add(Group.objects.get(name=group)) + + user.userpreference.space = space user.userpreference.save() c.force_login(user) return c -@pytest.fixture -def user_2(client, space_2): - c = copy.deepcopy(client) - with scopes_disabled(): - print(f'creating user 2 with space {space_2}') - user = User.objects.create(username='user_2') - user.groups.add(Group.objects.get(name='user')) - user.userpreference.space = space_2 - user.userpreference.save() - c.force_login(user) - return c +# anonymous user +@pytest.fixture() +def a_u(client): + return copy.deepcopy(client) + + +# users without any group +@pytest.fixture() +def ng1_s1(client, space_1): + return create_user(client, space_1) + + +@pytest.fixture() +def ng1_s2(client, space_2): + return create_user(client, space_2) + + +# guests +@pytest.fixture() +def g1_s1(client, space_1): + return create_user(client, space_1, group='guest') + + +@pytest.fixture() +def g2_s1(client, space_1): + return create_user(client, space_1, group='guest') + + +@pytest.fixture() +def g1_s2(client, space_2): + return create_user(client, space_2, group='guest') + + +@pytest.fixture() +def g2_s2(client, space_2): + return create_user(client, space_2, group='guest') + + +# users +@pytest.fixture() +def u1_s1(client, space_1): + return create_user(client, space_1, group='user') + + +@pytest.fixture() +def u2_s1(client, space_1): + return create_user(client, space_1, group='user') + + +@pytest.fixture() +def u1_s2(client, space_2): + return create_user(client, space_2, group='user') + + +@pytest.fixture() +def u2_s2(client, space_2): + return create_user(client, space_2, group='user') + + +# admins +@pytest.fixture() +def a1_s1(client, space_1): + return create_user(client, space_1, group='admin') + + +@pytest.fixture() +def a2_s1(client, space_1): + return create_user(client, space_1, group='admin') + + +@pytest.fixture() +def a1_s2(client, space_2): + return create_user(client, space_2, group='admin') + + +@pytest.fixture() +def a2_s2(client, space_2): + return create_user(client, space_2, group='admin') diff --git a/cookbook/tests/pytest/test_test.py b/cookbook/tests/pytest/test_test.py index 0053cc74..69894b63 100644 --- a/cookbook/tests/pytest/test_test.py +++ b/cookbook/tests/pytest/test_test.py @@ -10,16 +10,11 @@ from cookbook.models import Keyword, Space @pytest.mark.django_db -def test_user_create(user_2, user_1): - r = user_1.post(reverse('api:keyword-list'), {'name': 'test', 'space': 1}, content_type='application/json') +def test_user_create(u1_s1,u1_s2): + r = u1_s1.post(reverse('api:keyword-list'), {'name': 'test', 'space': 1}, content_type='application/json') response = json.loads(r.content) assert r.status_code == 201 assert response['name'] == 'test' - print('DEEEEEBUUUUUGGGG') - print(user_1.get(reverse('view_test')).content) - print(user_2.get(reverse('view_test')).content) - print(user_2) - - r = user_2.get(reverse('api:keyword-detail', args={response['id']}), content_type='application/json') + r = u1_s2.get(reverse('api:keyword-detail', args={response['id']}), content_type='application/json') assert r.status_code == 404 diff --git a/pytest.ini b/pytest.ini index 79e7a4e2..d766a842 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,3 +1,3 @@ [pytest] DJANGO_SETTINGS_MODULE = recipes.settings -python_files = tests.py test_*.py *_tests.py +python_files = tests.py test_*.py *_tests.py \ No newline at end of file From 528f329ebb5f808e9df63579b57e1eed95a4632d Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 10 Mar 2021 20:31:00 +0100 Subject: [PATCH 51/96] new keyword api test working --- cookbook/tests/pytest/__init__.py | 5 +- cookbook/tests/pytest/api/__init__.py | 5 +- cookbook/tests/pytest/api/test_api_keyword.py | 152 +++++++++++------- cookbook/tests/pytest/conftest.py | 12 ++ cookbook/views/api.py | 15 +- 5 files changed, 125 insertions(+), 64 deletions(-) diff --git a/cookbook/tests/pytest/__init__.py b/cookbook/tests/pytest/__init__.py index 255e8298..cd886345 100644 --- a/cookbook/tests/pytest/__init__.py +++ b/cookbook/tests/pytest/__init__.py @@ -1,6 +1,7 @@ from django.test import utils from django_scopes import scopes_disabled -# disables scoping error in all queries used inside the test functions -# fixtures need to have their own scopes_disabled +# disables scoping error in all queries used inside the test FUNCTIONS +# FIXTURES need to have their own scopes_disabled!! +# This is done by hook pytest_fixture_setup in conftest.py for all non yield fixtures utils.setup_databases = scopes_disabled()(utils.setup_databases) diff --git a/cookbook/tests/pytest/api/__init__.py b/cookbook/tests/pytest/api/__init__.py index 255e8298..cd886345 100644 --- a/cookbook/tests/pytest/api/__init__.py +++ b/cookbook/tests/pytest/api/__init__.py @@ -1,6 +1,7 @@ from django.test import utils from django_scopes import scopes_disabled -# disables scoping error in all queries used inside the test functions -# fixtures need to have their own scopes_disabled +# disables scoping error in all queries used inside the test FUNCTIONS +# FIXTURES need to have their own scopes_disabled!! +# This is done by hook pytest_fixture_setup in conftest.py for all non yield fixtures utils.setup_databases = scopes_disabled()(utils.setup_databases) diff --git a/cookbook/tests/pytest/api/test_api_keyword.py b/cookbook/tests/pytest/api/test_api_keyword.py index 6f7656ee..07e16cd1 100644 --- a/cookbook/tests/pytest/api/test_api_keyword.py +++ b/cookbook/tests/pytest/api/test_api_keyword.py @@ -9,13 +9,13 @@ from django.urls import reverse @pytest.fixture() -def keyword_1(): - return Keyword.objects.get_or_create(name='test_1')[0] +def obj_1(space_1): + return Keyword.objects.get_or_create(name='test_1', space=space_1)[0] @pytest.fixture -def keyword_2(): - return Keyword.objects.get_or_create(name='test_2')[0] +def obj_2(space_1): + return Keyword.objects.get_or_create(name='test_2', space=space_1)[0] @pytest.mark.parametrize("arg", [ @@ -29,66 +29,108 @@ def test_list_permission(arg, request): assert c.get(reverse('api:keyword-list')).status_code == arg[1] -def test_list_filter(keyword_1, keyword_2, u1_s1): +def test_list_filter(obj_1, obj_2, u1_s1): # verify storage is returned r = u1_s1.get(reverse('api:keyword-list')) assert r.status_code == 200 response = json.loads(r.content) assert len(response) == 2 - assert response[0]['name'] == keyword_1.name + assert response[0]['name'] == obj_1.name - response = json.loads(u1_s1.get(f'{reverse("api:keyword-list")}?limit=1')) + response = json.loads(u1_s1.get(f'{reverse("api:keyword-list")}?limit=1').content) assert len(response) == 1 - response = json.loads(u1_s1.get(f'{reverse("api:keyword-list")}?query=chicken')) + response = json.loads(u1_s1.get(f'{reverse("api:keyword-list")}?query=chicken').content) assert len(response) == 0 - response = json.loads(u1_s1.get(f'{reverse("api:keyword-list")}?query={keyword_1.name[4:]}')) + response = json.loads(u1_s1.get(f'{reverse("api:keyword-list")}?query={obj_1.name[4:]}').content) assert len(response) == 1 -# -# def test_keyword_update(self): -# r = self.user_client_1.patch( -# reverse( -# 'api:keyword-detail', -# args={self.keyword_1.id} -# ), -# {'name': 'new'}, -# content_type='application/json' -# ) -# response = json.loads(r.content) -# self.assertEqual(r.status_code, 200) -# self.assertEqual(response['name'], 'new') -# -# -# def test_keyword_add(self): -# r = self.user_client_1.post( -# reverse('api:keyword-list'), -# {'name': 'test'}, -# content_type='application/json' -# ) -# response = json.loads(r.content) -# self.assertEqual(r.status_code, 201) -# self.assertEqual(response['name'], 'test') -# -# -# def test_keyword_add_duplicate(self): -# r = self.user_client_1.post( -# reverse('api:keyword-list'), -# {'name': self.keyword_1.name}, -# content_type='application/json' -# ) -# response = json.loads(r.content) -# self.assertEqual(r.status_code, 201) -# self.assertEqual(response['name'], self.keyword_1.name) -# -# -# def test_keyword_delete(self): -# r = self.user_client_1.delete( -# reverse( -# 'api:keyword-detail', -# args={self.keyword_1.id} -# ) -# ) -# self.assertEqual(r.status_code, 204) -# self.assertEqual(Keyword.objects.count(), 1) + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], + ['g1_s2', 403], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + 'api:keyword-detail', + args={obj_1.id} + ), + {'name': 'new'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['name'] == 'new' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_keyword_add(arg, request, u1_s2): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse('api:keyword-list'), + {'name': 'test'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['name'] == 'test' + r = c.get(reverse('api:keyword-detail', args={response['id']})) + assert r.status_code == 200 + r = u1_s2.get(reverse('api:keyword-detail', args={response['id']})) + assert r.status_code == 404 + + +def test_add_duplicate(u1_s1, u1_s2, obj_1): + r = u1_s1.post( + reverse('api:keyword-list'), + {'name': obj_1.name}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == 201 + assert response['id'] == obj_1.id + + r = u1_s2.post( + reverse('api:keyword-list'), + {'name': obj_1.name}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == 201 + assert response['id'] != obj_1.id + + +def test_keyword_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + 'api:keyword-detail', + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + 'api:keyword-detail', + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert Keyword.objects.count() == 0 diff --git a/cookbook/tests/pytest/conftest.py b/cookbook/tests/pytest/conftest.py index a424b583..bb61d5ce 100644 --- a/cookbook/tests/pytest/conftest.py +++ b/cookbook/tests/pytest/conftest.py @@ -1,4 +1,5 @@ import copy +import inspect import uuid import pytest @@ -8,6 +9,17 @@ from django_scopes import scopes_disabled from cookbook.models import Space +# hack from https://github.com/raphaelm/django-scopes to disable scopes for all fixtures +# does not work on yield fixtures as only one yield can be used per fixture (i think) +@pytest.hookimpl(hookwrapper=True) +def pytest_fixture_setup(fixturedef, request): + if inspect.isgeneratorfunction(fixturedef.func): + yield + else: + with scopes_disabled(): + yield + + @pytest.fixture(autouse=True) def enable_db_access_for_all_tests(db): pass diff --git a/cookbook/views/api.py b/cookbook/views/api.py index d192dbd8..f3fe2941 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -152,7 +152,8 @@ class SupermarketViewSet(viewsets.ModelViewSet, StandardFilterMixin): permission_classes = [CustomIsUser] def get_queryset(self): - return self.queryset.filter(space=self.request.user.userpreference.space) + self.queryset = self.queryset.filter(space=self.request.user.userpreference.space) + return super().get_queryset() class KeywordViewSet(viewsets.ModelViewSet, StandardFilterMixin): @@ -169,7 +170,8 @@ class KeywordViewSet(viewsets.ModelViewSet, StandardFilterMixin): permission_classes = [CustomIsUser] def get_queryset(self): - return self.queryset.filter(space=self.request.user.userpreference.space) + self.queryset = self.queryset.filter(space=self.request.user.userpreference.space) + return super().get_queryset() class UnitViewSet(viewsets.ModelViewSet, StandardFilterMixin): @@ -178,7 +180,8 @@ class UnitViewSet(viewsets.ModelViewSet, StandardFilterMixin): permission_classes = [CustomIsUser] def get_queryset(self): - return self.queryset.filter(space=self.request.user.userpreference.space) + self.queryset = self.queryset.filter(space=self.request.user.userpreference.space) + return super().get_queryset() class FoodViewSet(viewsets.ModelViewSet, StandardFilterMixin): @@ -187,7 +190,8 @@ class FoodViewSet(viewsets.ModelViewSet, StandardFilterMixin): permission_classes = [CustomIsUser] def get_queryset(self): - return self.queryset.filter(space=self.request.user.userpreference.space) + self.queryset = self.queryset.filter(space=self.request.user.userpreference.space) + return super().get_queryset() class RecipeBookViewSet(viewsets.ModelViewSet, StandardFilterMixin): @@ -196,7 +200,8 @@ class RecipeBookViewSet(viewsets.ModelViewSet, StandardFilterMixin): permission_classes = [CustomIsOwner] def get_queryset(self): - return self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space) + self.queryset = self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space) + return super().get_queryset() class RecipeBookEntryViewSet(viewsets.ModelViewSet, viewsets.GenericViewSet): From e7f8d58a7d6837ee3b3ada8afdf1879dcc2168bb Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 10 Mar 2021 21:25:18 +0100 Subject: [PATCH 52/96] added test for cook log --- cookbook/serializer.py | 2 +- cookbook/tests/api/test_api_cook_log.py | 0 .../tests/pytest/api/test_api_cook_log.py | 116 ++++++++++++++++++ cookbook/tests/pytest/api/test_api_keyword.py | 41 ++++--- cookbook/tests/pytest/conftest.py | 17 ++- cookbook/views/api.py | 9 +- 6 files changed, 166 insertions(+), 19 deletions(-) delete mode 100644 cookbook/tests/api/test_api_cook_log.py create mode 100644 cookbook/tests/pytest/api/test_api_cook_log.py diff --git a/cookbook/serializer.py b/cookbook/serializer.py index e4b7bffe..60a601f0 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -382,7 +382,7 @@ class CookLogSerializer(serializers.ModelSerializer): class Meta: model = CookLog - fields = '__all__' + fields = ('id', 'recipe', 'servings', 'rating', 'created_by', 'created_at') read_only_fields = ('id', 'created_by') diff --git a/cookbook/tests/api/test_api_cook_log.py b/cookbook/tests/api/test_api_cook_log.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/pytest/api/test_api_cook_log.py b/cookbook/tests/pytest/api/test_api_cook_log.py new file mode 100644 index 00000000..fb2730f1 --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_cook_log.py @@ -0,0 +1,116 @@ +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import Keyword, CookLog + +LIST_URL = 'api:cooklog-list' +DETAIL_URL = 'api:cooklog-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1, recipe_1_s1): + return CookLog.objects.create(recipe=recipe_1_s1, created_by=auth.get_user(u1_s1), space=space_1) + + +@pytest.fixture +def obj_2(space_1, u1_s1, recipe_1_s1): + return CookLog.objects.create(recipe=recipe_1_s1, created_by=auth.get_user(u1_s1), space=space_1) + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 404], + ['u1_s1', 200], + ['a1_s1', 404], + ['g1_s2', 404], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'servings': 2}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['servings'] == 2 + + +# TODO disabled until https://github.com/vabene1111/recipes/issues/484 + +# @pytest.mark.parametrize("arg", [ +# ['a_u', 403], +# ['g1_s1', 201], +# ['u1_s1', 201], +# ['a1_s1', 201], +# ]) +# def test_add(arg, request, u1_s2, u2_s1, recipe_1_s1): +# c = request.getfixturevalue(arg[0]) +# r = c.post( +# reverse(LIST_URL), +# {'recipe': recipe_1_s1.id}, +# content_type='application/json' +# ) +# response = json.loads(r.content) +# assert r.status_code == arg[1] +# if r.status_code == 201: +# assert response['recipe'] == recipe_1_s1.id +# r = c.get(reverse(DETAIL_URL, args={response['id']})) +# assert r.status_code == 200 +# r = u2_s1.get(reverse(DETAIL_URL, args={response['id']})) +# assert r.status_code == 404 +# r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) +# assert r.status_code == 404 + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert CookLog.objects.count() == 0 diff --git a/cookbook/tests/pytest/api/test_api_keyword.py b/cookbook/tests/pytest/api/test_api_keyword.py index 07e16cd1..946e04f5 100644 --- a/cookbook/tests/pytest/api/test_api_keyword.py +++ b/cookbook/tests/pytest/api/test_api_keyword.py @@ -1,11 +1,13 @@ import json import pytest +from django.urls import reverse from django_scopes import scopes_disabled from cookbook.models import Keyword -from cookbook.tests.views.test_views import TestViews -from django.urls import reverse + +LIST_URL = 'api:keyword-list' +DETAIL_URL = 'api:keyword-detail' @pytest.fixture() @@ -26,12 +28,23 @@ def obj_2(space_1): ]) def test_list_permission(arg, request): c = request.getfixturevalue(arg[0]) - assert c.get(reverse('api:keyword-list')).status_code == arg[1] + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 1 def test_list_filter(obj_1, obj_2, u1_s1): # verify storage is returned - r = u1_s1.get(reverse('api:keyword-list')) + r = u1_s1.get(reverse(LIST_URL)) assert r.status_code == 200 response = json.loads(r.content) assert len(response) == 2 @@ -60,7 +73,7 @@ def test_update(arg, request, obj_1): c = request.getfixturevalue(arg[0]) r = c.patch( reverse( - 'api:keyword-detail', + DETAIL_URL, args={obj_1.id} ), {'name': 'new'}, @@ -78,10 +91,10 @@ def test_update(arg, request, obj_1): ['u1_s1', 201], ['a1_s1', 201], ]) -def test_keyword_add(arg, request, u1_s2): +def test_add(arg, request, u1_s2): c = request.getfixturevalue(arg[0]) r = c.post( - reverse('api:keyword-list'), + reverse(LIST_URL), {'name': 'test'}, content_type='application/json' ) @@ -89,15 +102,15 @@ def test_keyword_add(arg, request, u1_s2): assert r.status_code == arg[1] if r.status_code == 201: assert response['name'] == 'test' - r = c.get(reverse('api:keyword-detail', args={response['id']})) + r = c.get(reverse(DETAIL_URL, args={response['id']})) assert r.status_code == 200 - r = u1_s2.get(reverse('api:keyword-detail', args={response['id']})) + r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) assert r.status_code == 404 def test_add_duplicate(u1_s1, u1_s2, obj_1): r = u1_s1.post( - reverse('api:keyword-list'), + reverse(LIST_URL), {'name': obj_1.name}, content_type='application/json' ) @@ -106,7 +119,7 @@ def test_add_duplicate(u1_s1, u1_s2, obj_1): assert response['id'] == obj_1.id r = u1_s2.post( - reverse('api:keyword-list'), + reverse(LIST_URL), {'name': obj_1.name}, content_type='application/json' ) @@ -115,10 +128,10 @@ def test_add_duplicate(u1_s1, u1_s2, obj_1): assert response['id'] != obj_1.id -def test_keyword_delete(u1_s1, u1_s2, obj_1): +def test_delete(u1_s1, u1_s2, obj_1): r = u1_s2.delete( reverse( - 'api:keyword-detail', + DETAIL_URL, args={obj_1.id} ) ) @@ -126,7 +139,7 @@ def test_keyword_delete(u1_s1, u1_s2, obj_1): r = u1_s1.delete( reverse( - 'api:keyword-detail', + DETAIL_URL, args={obj_1.id} ) ) diff --git a/cookbook/tests/pytest/conftest.py b/cookbook/tests/pytest/conftest.py index bb61d5ce..75f0bb38 100644 --- a/cookbook/tests/pytest/conftest.py +++ b/cookbook/tests/pytest/conftest.py @@ -3,10 +3,11 @@ import inspect import uuid import pytest +from django.contrib import auth from django.contrib.auth.models import User, Group from django_scopes import scopes_disabled -from cookbook.models import Space +from cookbook.models import Space, Recipe # hack from https://github.com/raphaelm/django-scopes to disable scopes for all fixtures @@ -37,6 +38,20 @@ def space_2(): return Space.objects.get_or_create(name='space_2')[0] +# ---------------------- OBJECT FIXTURES --------------------- + +@pytest.fixture() +def recipe_1_s1(space_1, u1_s1): + return Recipe.objects.create( + name='recipe_1_s1', + waiting_time=20, + working_time=20, + servings=4, + created_by=auth.get_user(u1_s1), + space=space_1 + ) + + # ---------------------- USER FIXTURES ----------------------- # maybe better with factories but this is very explict so ... diff --git a/cookbook/views/api.py b/cookbook/views/api.py index f3fe2941..fcb02c05 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -382,7 +382,7 @@ class ViewLogViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsOwner] def get_queryset(self): - return CookLog.objects.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all()[:5] + return self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all()[:5] class CookLogViewSet(viewsets.ModelViewSet): @@ -391,8 +391,11 @@ class CookLogViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsOwner] def get_queryset(self): - queryset = CookLog.objects.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all()[:5] - return queryset + self.queryset = self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all() + if self.request.method == 'GET': + return self.queryset[:5] + else: + return self.queryset # -------------- non django rest api views -------------------- From d10c84b66eba202f3a855478885717c9df234122 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Wed, 10 Mar 2021 23:51:17 +0000 Subject: [PATCH 53/96] Apply translations in es translation completed for the source file '/cookbook/locale/en/LC_MESSAGES/django.po' on the 'es' language. --- cookbook/locale/es/LC_MESSAGES/django.po | 605 +++++++---------------- 1 file changed, 167 insertions(+), 438 deletions(-) diff --git a/cookbook/locale/es/LC_MESSAGES/django.po b/cookbook/locale/es/LC_MESSAGES/django.po index 6f89ca4d..a83c67de 100644 --- a/cookbook/locale/es/LC_MESSAGES/django.po +++ b/cookbook/locale/es/LC_MESSAGES/django.po @@ -2,11 +2,13 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# # Translators: # Alberto , 2020 # alfa5 , 2020 -# +# miguel angel , 2020 +# Miguel Canteras , 2021 +# #, fuzzy msgid "" msgstr "" @@ -14,13 +16,12 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-09 18:01+0100\n" "PO-Revision-Date: 2020-06-02 19:28+0000\n" -"Last-Translator: alfa5 , 2020\n" -"Language-Team: Spanish (https://www.transifex.com/django-recipes/" -"teams/110507/es/)\n" -"Language: es\n" +"Last-Translator: Miguel Canteras , 2021\n" +"Language-Team: Spanish (https://www.transifex.com/django-recipes/teams/110507/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: es\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: .\cookbook\filters.py:22 .\cookbook\templates\base.html:87 @@ -35,8 +36,8 @@ msgid "" "Color of the top navigation bar. Not all colors work with all themes, just " "try them out!" msgstr "" -"Color de la barra de navegación superior. No todos los colores funcionan con " -"todos los temas, ¡pruébalos!" +"Color de la barra de navegación superior. No todos los colores funcionan con" +" todos los temas, ¡pruébalos!" #: .\cookbook\forms.py:45 msgid "Default Unit to be used when inserting a new ingredient into a recipe." @@ -57,8 +58,8 @@ msgid "" "Users with whom newly created meal plan/shopping list entries should be " "shared by default." msgstr "" -"Usuarios con los que las entradas recién creado plan de comida/lista de la " -"compra deben compartirse de forma predeterminada." +"Usuarios con los que las entradas recién creadas del plan de comida/lista de" +" la compra deben compartirse de forma predeterminada." #: .\cookbook\forms.py:48 msgid "Show recently viewed recipes on search page." @@ -79,8 +80,8 @@ msgid "" "Useful when shopping with multiple people but might use a little bit of " "mobile data. If lower than instance limit it is reset when saving." msgstr "" -"Ponerlo a 0 deshabilitará la sincronización automática. Al ver una lista de " -"la compra, la lista se actualiza cada periodo establecido en segundos para " +"Fijar en 0 deshabilita la sincronización automática. Al ver una lista de la " +"compra, la lista se actualiza cada periodo establecido de segundos para " "sincronizar los cambios que otra persona pueda haber hecho. Es útil cuando " "se compra con varias personas, pero puede consumir datos móviles. Si el " "valor establecido es inferior al límite de la instancia, este se " @@ -88,15 +89,14 @@ msgstr "" #: .\cookbook\forms.py:55 msgid "Makes the navbar stick to the top of the page." -msgstr "" +msgstr "Hace la barra de navegación fija en la parte superior de la página." #: .\cookbook\forms.py:71 msgid "" "Both fields are optional. If none are given the username will be displayed " "instead" msgstr "" -"Ambos campos son opcionales. Si no se proporciona ninguno, se mostrará el " -"nombre de usuario en su lugar\n" +"Ambos campos son opcionales. Si no se proporciona ninguno, se mostrará el nombre de usuario en su lugar\n" " \n" " \n" " \n" @@ -131,10 +131,8 @@ msgid "Storage UID" msgstr "UID de almacenamiento" #: .\cookbook\forms.py:117 -#, fuzzy -#| msgid "Number of Days" msgid "Number of servings" -msgstr "Número de Días" +msgstr "Número de raciones" #: .\cookbook\forms.py:128 msgid "" @@ -146,7 +144,7 @@ msgstr "" #: .\cookbook\forms.py:143 msgid "Default" -msgstr "" +msgstr "Por defecto" #: .\cookbook\forms.py:162 msgid "New Unit" @@ -154,15 +152,15 @@ msgstr "Nueva Unidad" #: .\cookbook\forms.py:163 msgid "New unit that other gets replaced by." -msgstr "Nueva unidad por la que otras son reemplazadas." +msgstr "Nueva unidad que reemplaza a la anterior." #: .\cookbook\forms.py:168 msgid "Old Unit" -msgstr "Unidad antigua" +msgstr "Antigua unidad" #: .\cookbook\forms.py:169 msgid "Unit that should be replaced." -msgstr "Unidad que debe reemplazarse." +msgstr "Unidad que se va a reemplazar." #: .\cookbook\forms.py:179 msgid "New Food" @@ -174,7 +172,7 @@ msgstr "Nuevo alimento que remplaza al anterior." #: .\cookbook\forms.py:185 msgid "Old Food" -msgstr "Alimento anterior" +msgstr "Antiguo alimento" #: .\cookbook\forms.py:186 msgid "Food that should be replaced." @@ -197,8 +195,8 @@ msgstr "" #: .\cookbook\forms.py:244 msgid "" -"Leave empty for dropbox and enter only base url for nextcloud (/remote." -"php/webdav/ is added automatically)" +"Leave empty for dropbox and enter only base url for nextcloud " +"(/remote.php/webdav/ is added automatically)" msgstr "" "Dejar vació para Dropbox e introducir sólo la URL base para Nextcloud " "(/remote.php/webdav/ se añade automáticamente)" @@ -218,17 +216,17 @@ msgstr "Debe proporcionar al menos una receta o un título." #: .\cookbook\forms.py:312 msgid "You can list default users to share recipes with in the settings." msgstr "" -"Puede enumerar los usuarios predeterminados con los que compartir recetas en " -"la configuración." +"Puede enumerar los usuarios predeterminados con los que compartir recetas en" +" la configuración." #: .\cookbook\forms.py:313 #: .\cookbook\templates\forms\edit_internal_recipe.html:377 msgid "" -"You can use markdown to format this field. See the docs here" +"You can use markdown to format this field. See the docs here" msgstr "" -"Puede utilizar Markdown para formatear este campo. Vea la documentación aqui" +"Puede utilizar Markdown para formatear este campo. Vea la documentación aqui" #: .\cookbook\forms.py:328 msgid "A username is not required, if left blank the new user can choose one." @@ -263,8 +261,8 @@ msgstr "" #: .\cookbook\helper\recipe_url_import.py:53 msgid "" -"The requested site does not provide any recognized data format to import the " -"recipe from." +"The requested site does not provide any recognized data format to import the" +" recipe from." msgstr "" "El sitio solicitado no proporciona ningún formato de datos reconocido para " "importar la receta." @@ -278,6 +276,8 @@ msgid "" "Importer expected a .zip file. Did you choose the correct importer type for " "your data ?" msgstr "" +"El importador esperaba un fichero.zip. ¿Has escogido el tipo de importador " +"correcto para tus datos?" #: .\cookbook\integration\safron.py:23 #: .\cookbook\templates\forms\edit_internal_recipe.html:65 @@ -287,10 +287,8 @@ msgid "Servings" msgstr "Raciones" #: .\cookbook\integration\safron.py:25 -#, fuzzy -#| msgid "Waiting time ~" msgid "Waiting time" -msgstr "Tiempo de espera ~" +msgstr "Tiempo de espera" #: .\cookbook\integration\safron.py:27 #: .\cookbook\templates\forms\edit_internal_recipe.html:59 @@ -305,7 +303,7 @@ msgstr "Libro de cocina" #: .\cookbook\integration\safron.py:31 msgid "Section" -msgstr "" +msgstr "Sección" #: .\cookbook\migrations\0047_auto_20200602_1133.py:12 msgid "Breakfast" @@ -401,37 +399,36 @@ msgstr "Iniciar sesión" #: .\cookbook\templates\account\login.html:13 #: .\cookbook\templates\account\login.html:28 msgid "Sign In" -msgstr "" +msgstr "Iniciar sesión" #: .\cookbook\templates\account\login.html:38 msgid "Social Login" -msgstr "" +msgstr "Inicio de sesión social" #: .\cookbook\templates\account\login.html:39 msgid "You can use any of the following providers to sign in." msgstr "" +"Puedes usar cualquiera de los siguientes proveedores de inicio de sesión." #: .\cookbook\templates\account\logout.html:5 #: .\cookbook\templates\account\logout.html:9 #: .\cookbook\templates\account\logout.html:18 msgid "Sign Out" -msgstr "" +msgstr "Salir" #: .\cookbook\templates\account\logout.html:11 -#, fuzzy -#| msgid "Are you sure that you want to merge these two units?" msgid "Are you sure you want to sign out?" -msgstr "¿Estás seguro de que quieres combinar estas dos unidades?" +msgstr "¿Seguro que quieres salir?" #: .\cookbook\templates\account\password_reset.html:5 #: .\cookbook\templates\account\password_reset_done.html:5 msgid "Password Reset" -msgstr "" +msgstr "Restablecer contraseña" #: .\cookbook\templates\account\password_reset.html:9 #: .\cookbook\templates\account\password_reset_done.html:9 msgid "Password reset is not implemented for the time being!" -msgstr "" +msgstr "¡Restablecimiento de contraseña no está implementado de momento!" #: .\cookbook\templates\account\signup.html:5 msgid "Register" @@ -649,20 +646,16 @@ msgid "Waiting Time" msgstr "Tiempo de espera" #: .\cookbook\templates\forms\edit_internal_recipe.html:68 -#, fuzzy -#| msgid "Servings" msgid "Servings Text" -msgstr "Raciones" +msgstr "Texto de raciones" #: .\cookbook\templates\forms\edit_internal_recipe.html:79 msgid "Select Keywords" msgstr "Seleccionar palabras clave" #: .\cookbook\templates\forms\edit_internal_recipe.html:93 -#, fuzzy -#| msgid "Nutrition" msgid "Description" -msgstr "Información Nutricional" +msgstr "Descripción" #: .\cookbook\templates\forms\edit_internal_recipe.html:108 msgid "Nutrition" @@ -778,7 +771,7 @@ msgstr "Habilitar cantidad" #: .\cookbook\templates\forms\edit_internal_recipe.html:348 msgid "Copy Template Reference" -msgstr "" +msgstr "Copiar Referencia de Plantilla" #: .\cookbook\templates\forms\edit_internal_recipe.html:374 #: .\cookbook\templates\url_import.html:177 @@ -826,19 +819,15 @@ msgstr "Editar ingredientes" #: .\cookbook\templates\forms\ingredients.html:16 msgid "" "\n" -" The following form can be used if, accidentally, two (or more) units " -"or ingredients where created that should be\n" +" The following form can be used if, accidentally, two (or more) units or ingredients where created that should be\n" " the same.\n" -" It merges two units or ingredients and updates all recipes using " -"them.\n" +" It merges two units or ingredients and updates all recipes using them.\n" " " msgstr "" "\n" -" La siguiente forma puede utilizarse si, accidentalmente, se crean " -"dos (o más) unidades o ingredientes que deberían ser\n" +" La siguiente forma puede utilizarse si, accidentalmente, se crean dos (o más) unidades o ingredientes que deberían ser\n" " iguales.\n" -" Fusiona dos unidades o ingredientes y actualiza todas las recetas " -"que los usan.\n" +" Fusiona dos unidades o ingredientes y actualiza todas las recetas que los usan.\n" " " #: .\cookbook\templates\forms\ingredients.html:24 @@ -853,7 +842,7 @@ msgstr "¿Estás seguro de que quieres combinar estas dos unidades?" #: .\cookbook\templates\forms\ingredients.html:31 #: .\cookbook\templates\forms\ingredients.html:40 msgid "Merge" -msgstr "Unir" +msgstr "Combinar" #: .\cookbook\templates\forms\ingredients.html:36 msgid "Are you sure that you want to merge these two ingredients?" @@ -879,7 +868,7 @@ msgstr "Eliminar archivo original" #: .\cookbook\templates\generic\list_template.html:6 #: .\cookbook\templates\generic\list_template.html:12 msgid "List" -msgstr "Listar" +msgstr "Lista" #: .\cookbook\templates\generic\list_template.html:25 msgid "Filter" @@ -961,23 +950,17 @@ msgstr "Advertencia de seguridad" #: .\cookbook\templates\include\storage_backend_warning.html:5 msgid "" "\n" -" The Password and Token field are stored as plain text " -"inside the database.\n" -" This is necessary because they are needed to make API requests, but " -"it also increases the risk of\n" +" The Password and Token field are stored as plain text inside the database.\n" +" This is necessary because they are needed to make API requests, but it also increases the risk of\n" " someone stealing it.
\n" -" To limit the possible damage tokens or accounts with limited access " -"can be used.\n" +" To limit the possible damage tokens or accounts with limited access can be used.\n" " " msgstr "" "\n" -" Los camposContraseña y Tokenson almacenados en texto " -"plano dentro de la base de datos.\n" -" Esto es necesario porque son requeridos para hacer peticiones de la " -"API, pero esto incrementa el riesgo de\n" +" Los camposContraseña y Tokenson almacenados en texto plano dentro de la base de datos.\n" +" Esto es necesario porque son requeridos para hacer peticiones de la API, pero esto incrementa el riesgo de\n" " que alguien lo robe.
\n" -" Para limitar los posibles daños se pueden utilizar tokens o cuentas " -"con acceso limitado.\n" +" Para limitar los posibles daños se pueden utilizar tokens o cuentas con acceso limitado.\n" " " #: .\cookbook\templates\index.html:29 @@ -1011,7 +994,7 @@ msgstr "Recetas" #: .\cookbook\templates\index.html:94 msgid "Log in to view recipes" -msgstr "Inicie sesión para ver recetas" +msgstr "Inicia sesión para ver recetas" #: .\cookbook\templates\markdown_info.html:5 #: .\cookbook\templates\markdown_info.html:13 @@ -1021,30 +1004,16 @@ msgstr "Información de Markdown" #: .\cookbook\templates\markdown_info.html:14 msgid "" "\n" -" Markdown is lightweight markup language that can be used to format " -"plain text easily.\n" -" This site uses the Python Markdown library to\n" -" convert your text into nice looking HTML. Its full markdown " -"documentation can be found\n" -" here.\n" -" An incomplete but most likely sufficient documentation can be found " -"below.\n" +" Markdown is lightweight markup language that can be used to format plain text easily.\n" +" This site uses the Python Markdown library to\n" +" convert your text into nice looking HTML. Its full markdown documentation can be found\n" +" here.\n" +" An incomplete but most likely sufficient documentation can be found below.\n" " " msgstr "" "\n" -" Markdown es un lenguaje de marcado ligero que puede ser usado para " -"formatear fácilmente el texto.\n" -" Este sitio utiliza la biblioteca Python Markdown para\n" -" convertir tu texto en un bonito html. La documentación completa de " -"Markdown se puede encontrar\n" -" aquí.\n" -" A continuación se incluye una documentación incompleta pero " -"probablemente suficiente.\n" -" " +"Markdown es un lenguaje de marcado ligero que puede usarse para formatear texto plano fácilmente. Este sitio usa la librería Python Markdownpara convertir tu texto en HTML atractivo. Su documentación completa puede ser encontrada aquí.\n" +"Una documentación incompleta pero suficiente puede encontrarse a continuación." #: .\cookbook\templates\markdown_info.html:25 msgid "Headers" @@ -1074,7 +1043,7 @@ msgstr "Este texto está en negrita" #: .\cookbook\templates\markdown_info.html:60 #: .\cookbook\templates\markdown_info.html:75 msgid "This text is italic" -msgstr "Este texto está en cursiva" +msgstr "Este texto está en itálica." #: .\cookbook\templates\markdown_info.html:61 #: .\cookbook\templates\markdown_info.html:77 @@ -1130,8 +1099,8 @@ msgid "" "Links can be formatted with Markdown. This application also allows to paste " "links directly into markdown fields without any formatting." msgstr "" -"Los enlaces se pueden formatear con Markdown. Esta aplicación también " -"permite pegar enlaces directamente en campos de Markdown sin ningun formato." +"Los enlaces pueden ser formateados con Markdown. Esta aplicación también " +"permite pegar enlaces directamente en campos markdown sin formato." #: .\cookbook\templates\markdown_info.html:132 #: .\cookbook\templates\markdown_info.html:145 @@ -1143,19 +1112,15 @@ msgid "Tables" msgstr "Tablas" #: .\cookbook\templates\markdown_info.html:153 -#, fuzzy -#| msgid "" -#| "Markdown tables are hard to create by hand. It is recommended to use a " -#| "table editor like this one." msgid "" -"Markdown tables are hard to create by hand. It is recommended to use a table " -"editor like this one." +"Markdown tables are hard to create by hand. It is recommended to use a table" +" editor like this one." msgstr "" -"Las tablas de Markdown son difíciles de crear a mano. Se recomienda usar un " -"editor de tablas como este. " +"Las tablas Mardown son difíciles de crear a mano. Se recomienda usar un " +"editor de tablas como este." #: .\cookbook\templates\markdown_info.html:155 #: .\cookbook\templates\markdown_info.html:157 @@ -1193,19 +1158,18 @@ msgstr "Nota (opcional)" #: .\cookbook\templates\meal_plan.html:143 msgid "" -"You can use markdown to format this field. See the docs here" +"You can use markdown to format this field. See the docs " +"here" msgstr "" -"Puedes utilizar Markdown para dar formato a este campo. Consulta la documentación aquí" +"Puedes utilizar Markdown para dar formato a este campo. Consulta la documentación aquí" #: .\cookbook\templates\meal_plan.html:147 #: .\cookbook\templates\meal_plan.html:251 -#, fuzzy -#| msgid "Servings" msgid "Serving Count" -msgstr "Raciones" +msgstr "Número de raciones" #: .\cookbook\templates\meal_plan.html:153 msgid "Create only note" @@ -1220,7 +1184,7 @@ msgstr "Lista de la Compra" #: .\cookbook\templates\meal_plan.html:172 msgid "Shopping list currently empty" -msgstr "La Lista de la Compra está vacía" +msgstr "Lista de la compra vacía" #: .\cookbook\templates\meal_plan.html:175 msgid "Open Shopping List" @@ -1240,8 +1204,8 @@ msgstr "Compensar día inicial" #: .\cookbook\templates\meal_plan.html:209 msgid "" -"Number of days starting from the first day of the week to offset the default " -"view." +"Number of days starting from the first day of the week to offset the default" +" view." msgstr "" "Número de días a partir del primer día de la semana para compensar la vista " "por defecto." @@ -1283,104 +1247,44 @@ msgid "Meal Plan Help" msgstr "Ayuda del menú" #: .\cookbook\templates\meal_plan.html:344 -#, fuzzy -#| msgid "" -#| "\n" -#| "

The meal plan module allows planning of " -#| "meals both with recipes and notes.

\n" -#| "

Simply select a recipe from the list of " -#| "recently viewed recipes or search the one you\n" -#| " want and drag it to the desired plan " -#| "position. You can also add a note and a title and\n" -#| " then drag the recipe to create a plan " -#| "entry with a custom title and note. Creating only\n" -#| " Notes is possible by dragging the create " -#| "note box into the plan.

\n" -#| "

Click on a recipe in order to open the " -#| "detail view. Here you can also add it to the\n" -#| " shopping list. You can also add all " -#| "recipes of a day to the shopping list by\n" -#| " clicking the shopping cart at the top of " -#| "the table.

\n" -#| "

Since a common use case is to plan meals " -#| "together you can define\n" -#| " users you want to share your plan with in " -#| "the settings.\n" -#| "

\n" -#| "

You can also edit the types of meals you " -#| "want to plan. If you share your plan with\n" -#| " someone with\n" -#| " different meals, their meal types will " -#| "appear in your list as well. To prevent\n" -#| " duplicates (e.g. Other and Misc.)\n" -#| " name your meal types the same as the " -#| "users you share your meals with and they will be\n" -#| " merged.

\n" -#| " " msgid "" "\n" -"

The meal plan module allows planning of meals " -"both with recipes and notes.

\n" -"

Simply select a recipe from the list of " -"recently viewed recipes or search the one you\n" -" want and drag it to the desired plan " -"position. You can also add a note and a title and\n" -" then drag the recipe to create a plan entry " -"with a custom title and note. Creating only\n" -" Notes is possible by dragging the create " -"note box into the plan.

\n" -"

Click on a recipe in order to open the " -"detailed view. There you can also add it to the\n" -" shopping list. You can also add all recipes " -"of a day to the shopping list by\n" -" clicking the shopping cart at the top of the " -"table.

\n" -"

Since a common use case is to plan meals " -"together you can define\n" -" users you want to share your plan with in " -"the settings.\n" +"

The meal plan module allows planning of meals both with recipes and notes.

\n" +"

Simply select a recipe from the list of recently viewed recipes or search the one you\n" +" want and drag it to the desired plan position. You can also add a note and a title and\n" +" then drag the recipe to create a plan entry with a custom title and note. Creating only\n" +" Notes is possible by dragging the create note box into the plan.

\n" +"

Click on a recipe in order to open the detailed view. There you can also add it to the\n" +" shopping list. You can also add all recipes of a day to the shopping list by\n" +" clicking the shopping cart at the top of the table.

\n" +"

Since a common use case is to plan meals together you can define\n" +" users you want to share your plan with in the settings.\n" "

\n" -"

You can also edit the types of meals you want " -"to plan. If you share your plan with\n" +"

You can also edit the types of meals you want to plan. If you share your plan with\n" " someone with\n" -" different meals, their meal types will " -"appear in your list as well. To prevent\n" +" different meals, their meal types will appear in your list as well. To prevent\n" " duplicates (e.g. Other and Misc.)\n" -" name your meal types the same as the users " -"you share your meals with and they will be\n" +" name your meal types the same as the users you share your meals with and they will be\n" " merged.

\n" " " msgstr "" "\n" -"

El módulo de menú permite planificar las " -"comidas con recetas o con notas.

\n" -"

Simplemente selecciona una receta de la lista " -"de recetas vistas recientemente o busca la que\n" -" quieras y arrastrala a la posición deseada " -"del menú. También puede añadir una nota y un título y\n" -" luego arrastrar la receta para crear una " -"entrada del plan con un título y una nota personalizados. Es posible crear\n" -" solamente notas arrastrando el cuadro de " -"creación de notas al menú.

\n" -"

Haga clic en una receta para abrir la vista " -"detallada. Desde aquí también puedes añadirla a la\n" -" lista de la compra. También puedes añadir " -"todas las recetas de un día a la lista de la compra\n" -" haciendo clic en el carrito de la compra en " -"la parte superior de la tabla.

\n" -"

Ya que un caso de uso común es planificar las " -"comidas juntos, en los ajustes\n" -" puedes definir los usuarios con los que " -"quieres compartir el menú.\n" +"

El módulo de menú permite planificar las comidas con recetas o con notas.

\n" +"

Simplemente selecciona una receta de la lista de recetas vistas recientemente o busca la que\n" +" quieras y arrastrala a la posición deseada del menú. También puede añadir una nota y un título y\n" +" luego arrastrar la receta para crear una entrada del plan con un título y una nota personalizados. Es posible crear\n" +" solamente notas arrastrando el cuadro de creación de notas al menú.

\n" +"

Haga clic en una receta para abrir la vista detallada. Desde aquí también puedes añadirla a la\n" +" lista de la compra. También puedes añadir todas las recetas de un día a la lista de la compra\n" +" haciendo clic en el carrito de la compra en la parte superior de la tabla.

\n" +"

Ya que un caso de uso común es planificar las comidas juntos, en los ajustes\n" +" puedes definir los usuarios con los que quieres compartir el menú.\n" "

\n" -"

También puedes editar los tipos de comidas " -"del menú. Si compartes tu menú con\n" +"

También puedes editar los tipos de comidas del menú. Si compartes tu menú con\n" " alguien con\n" -" diferentes tipos de comidas, sus tipos de " -"comida aparecerán también en tu listado. Para prevenir\n" +" diferentes tipos de comidas, sus tipos de comida aparecerán también en tu listado. Para prevenir\n" " duplicados (p. ej. Otros y Misc.)\n" -" nombra los tipos de comida igual que el " -"resto de usuarios con los que compartes tus comidas y serán\n" +" nombra los tipos de comida igual que el resto de usuarios con los que compartes tus comidas y serán\n" " combinados.

\n" " " @@ -1399,27 +1303,32 @@ msgstr "Otras comidas en este día" #: .\cookbook\templates\no_groups_info.html:5 #: .\cookbook\templates\offline.html:6 msgid "Offline" -msgstr "" +msgstr "Desconectado" #: .\cookbook\templates\no_groups_info.html:12 msgid "No Permissions" -msgstr "" +msgstr "Sin permisos" #: .\cookbook\templates\no_groups_info.html:15 msgid "" "You do not have any groups and therefor cannot use this application. Please " "contact your administrator." msgstr "" +"No tienes ningún grupo y por eso no puedes usar esta aplicación. Por favor, " +"contacta con tu administrador." #: .\cookbook\templates\offline.html:19 msgid "You are currently offline!" -msgstr "" +msgstr "¡Estás desconectado!" #: .\cookbook\templates\offline.html:20 msgid "" "The recipes listed below are available for offline viewing because you have " "recently viewed them. Keep in mind that data might be outdated." msgstr "" +"Las recetas listadas a continuación están disponibles para ver sin conexión " +"porque las has visto recientemente. Ten en cuenta que los datos pueden estar" +" desactualizados." #: .\cookbook\templates\recipe_view.html:21 .\cookbook\templates\stats.html:47 msgid "Comments" @@ -1464,7 +1373,7 @@ msgstr "Cuenta" #: .\cookbook\templates\settings.html:38 msgid "Link social account" -msgstr "" +msgstr "Enlazar cuenta social" #: .\cookbook\templates\settings.html:42 msgid "Language" @@ -1488,8 +1397,8 @@ msgstr "" #: .\cookbook\templates\settings.html:92 msgid "" -"Use the token as an Authorization header prefixed by the word token as shown " -"in the following examples:" +"Use the token as an Authorization header prefixed by the word token as shown" +" in the following examples:" msgstr "" "Utilice el token como cabecera de autorización usando como prefijo la " "palabra token, tal y como se muestra en los siguientes ejemplos:" @@ -1510,11 +1419,12 @@ msgstr "Configuración" msgid "" "To start using this application you must first create a superuser account." msgstr "" -"Para empezar a usar esta aplicación, primero debes crear un superusuario." +"Para empezar a usar esta aplicación primero tienes que crear una cuenta de " +"superusuario." #: .\cookbook\templates\setup.html:20 msgid "Create Superuser account" -msgstr "Crear Superusuario" +msgstr "Crear cuenta de Superusuario" #: .\cookbook\templates\shopping_list.html:75 msgid "Shopping Recipes" @@ -1526,13 +1436,11 @@ msgstr "No hay recetas seleccionadas" #: .\cookbook\templates\shopping_list.html:145 msgid "Entry Mode" -msgstr "" +msgstr "Modo de entrada" #: .\cookbook\templates\shopping_list.html:153 -#, fuzzy -#| msgid "New Entry" msgid "Add Entry" -msgstr "Nueva entrada" +msgstr "Añadir entrada" #: .\cookbook\templates\shopping_list.html:168 msgid "Amount" @@ -1540,13 +1448,11 @@ msgstr "Cantidad" #: .\cookbook\templates\shopping_list.html:224 msgid "Supermarket" -msgstr "" +msgstr "Supermercado" #: .\cookbook\templates\shopping_list.html:234 -#, fuzzy -#| msgid "Select User" msgid "Select Supermarket" -msgstr "Seleccionar Usuario" +msgstr "Seleccionar supermercado" #: .\cookbook\templates\shopping_list.html:258 msgid "Select User" @@ -1558,8 +1464,7 @@ msgstr "Completada" #: .\cookbook\templates\shopping_list.html:290 msgid "You are offline, shopping list might not syncronize." -msgstr "" -"Estás desconectado, la lista de la compra podría no estar sincronizada." +msgstr "Estás desconectado, la lista de la compra no se sincronizará." #: .\cookbook\templates\shopping_list.html:353 msgid "Copy/Export" @@ -1576,26 +1481,28 @@ msgstr "¡Hubo un error al crear un recurso!" #: .\cookbook\templates\socialaccount\connections.html:4 #: .\cookbook\templates\socialaccount\connections.html:7 msgid "Account Connections" -msgstr "" +msgstr "Conexiones de la cuenta" #: .\cookbook\templates\socialaccount\connections.html:10 msgid "" "You can sign in to your account using any of the following third party\n" " accounts:" msgstr "" +"Puedes entrar en tu cuenta usando cualquiera de las siguientes cuentas de " +"terceros:" #: .\cookbook\templates\socialaccount\connections.html:36 msgid "Remove" -msgstr "" +msgstr "Eliminar" #: .\cookbook\templates\socialaccount\connections.html:44 msgid "" "You currently have no social network accounts connected to this account." -msgstr "" +msgstr "Actualmente no tienes una cuenta social conectada a esta cuenta." #: .\cookbook\templates\socialaccount\connections.html:47 msgid "Add a 3rd Party Account" -msgstr "" +msgstr "Añadir una cuenta de terceros" #: .\cookbook\templates\stats.html:4 msgid "Stats" @@ -1648,19 +1555,15 @@ msgstr "Información del Sistema" #: .\cookbook\templates\system.html:51 msgid "" "\n" -" Django Recipes is an open source free software application. It can " -"be found on\n" +" Django Recipes is an open source free software application. It can be found on\n" " GitHub.\n" -" Changelogs can be found here.\n" +" Changelogs can be found here.\n" " " msgstr "" "\n" -" Django Recipes es una aplicación de software libre de código " -"abierto. Se puede encontrar en\n" +" Django Recipes es una aplicación de software libre de código abierto. Se puede encontrar en\n" " GitHub.\n" -" Los registros de cambios se pueden encontrar aquí.\n" +" Los registros de cambios se pueden encontrar aquí.\n" " " #: .\cookbook\templates\system.html:65 @@ -1681,16 +1584,13 @@ msgstr "Ok" msgid "" "Serving media files directly using gunicorn/python is not recommend!\n" " Please follow the steps described\n" -" here to update\n" +" here to update\n" " your installation.\n" " " msgstr "" -"Servir archivos multimedia utilizando directamente gunicorn/python no " -"está recomendado!\n" +"Servir archivos multimedia utilizando directamente gunicorn/python no está recomendado!\n" " Por favor, sigue los pasos descritos\n" -" aquí para actualizar\n" +" aquí para actualizar\n" " tu instalación.\n" " " @@ -1706,23 +1606,17 @@ msgstr "Clave Secreta" #: .\cookbook\templates\system.html:83 msgid "" "\n" -" You do not have a SECRET_KEY configured in your " -".env file. Django defaulted to the\n" +" You do not have a SECRET_KEY configured in your .env file. Django defaulted to the\n" " standard key\n" -" provided with the installation which is publicly know and " -"insecure! Please set\n" -" SECRET_KEY int the .env configuration " -"file.\n" +" provided with the installation which is publicly know and insecure! Please set\n" +" SECRET_KEY int the .env configuration file.\n" " " msgstr "" "\n" -" No has configurado la variable SECRET_KEY en el " -"fichero .env. Django está utilizando la\n" +" No has configurado la variable SECRET_KEY en el fichero .env. Django está utilizando la\n" " clave estándar\n" -" proporcionada con la instalación, esta clave es pública e " -"insegura. Por favor, configura\n" -" SECRET_KEY en el fichero de configuración ." -"env.\n" +" proporcionada con la instalación, esta clave es pública e insegura. Por favor, configura\n" +" SECRET_KEY en el fichero de configuración .env.\n" " " #: .\cookbook\templates\system.html:95 @@ -1732,19 +1626,15 @@ msgstr "Modo Depuración" #: .\cookbook\templates\system.html:99 msgid "" "\n" -" This application is still running in debug mode. This is most " -"likely not needed. Turn of debug mode by\n" +" This application is still running in debug mode. This is most likely not needed. Turn of debug mode by\n" " setting\n" -" DEBUG=0 int the .env configuration " -"file.\n" +" DEBUG=0 int the .env configuration file.\n" " " msgstr "" "\n" -" Esta aplicación está funcionando en modo de depuración. Lo más " -"probable es que no sea necesario. Para desactivar el modo de depuración\n" +" Esta aplicación está funcionando en modo de depuración. Lo más probable es que no sea necesario. Para desactivar el modo de depuración\n" " configura\n" -" DEBUG=0 en el fichero de configuración .env.\n" +" DEBUG=0 en el fichero de configuración .env.\n" " " #: .\cookbook\templates\system.html:110 @@ -1758,14 +1648,12 @@ msgstr "Información" #: .\cookbook\templates\system.html:114 msgid "" "\n" -" This application is not running with a Postgres database " -"backend. This is ok but not recommended as some\n" +" This application is not running with a Postgres database backend. This is ok but not recommended as some\n" " features only work with postgres databases.\n" " " msgstr "" "\n" -" Esta aplicación no se ejecuta con un backend de base de datos " -"Postgres. Esto es válido pero no es recomendado ya que algunas\n" +" Esta aplicación no se ejecuta con un backend de base de datos Postgres. Esto es válido pero no es recomendado ya que algunas\n" " características sólo funcionan con bases de datos Postgres.\n" " " @@ -1793,7 +1681,7 @@ msgstr "Todas las palabras clave." #: .\cookbook\templates\url_import.html:206 msgid "Import all keywords, not only the ones already existing." -msgstr "Importar todas las palabras clave no sólo las ya existentes." +msgstr "Importar todas las palabras clave, no solo las ya existentes." #: .\cookbook\templates\url_import.html:233 msgid "Information" @@ -1802,20 +1690,15 @@ msgstr "Información" #: .\cookbook\templates\url_import.html:235 msgid "" " Only websites containing ld+json or microdata information can currently\n" -" be imported. Most big recipe pages " -"support this. If you site cannot be imported but\n" +" be imported. Most big recipe pages support this. If you site cannot be imported but\n" " you think\n" -" it probably has some kind of structured " -"data feel free to post an example in the\n" +" it probably has some kind of structured data feel free to post an example in the\n" " github issues." msgstr "" "Actualmente sólo se pueden importar sitios web que contengan información en\n" -" ld+json o microdatos. La mayoría de las " -"grandes páginas de recetas soportan esto. Si tu sitio no puede ser importado " -"pero \n" +" ld+json o microdatos. La mayoría de las grandes páginas de recetas soportan esto. Si tu sitio no puede ser importado pero \n" " crees que\n" -" tiene algún tipo de datos estructurados, " -"no dudes en poner un ejemplo en las\n" +" tiene algún tipo de datos estructurados, no dudes en poner un ejemplo en las\n" " propuestas de GitHub." #: .\cookbook\templates\url_import.html:243 @@ -1840,7 +1723,7 @@ msgstr "Las preferencias para este usuario ya existen" #: .\cookbook\views\api.py:416 .\cookbook\views\views.py:265 msgid "This feature is not available in the demo version!" -msgstr "" +msgstr "¡Esta funcionalidad no está disponible en la versión demo!" #: .\cookbook\views\api.py:439 msgid "Sync successful!" @@ -1931,7 +1814,7 @@ msgstr "¡Unidades fusionadas!" #: .\cookbook\views\edit.py:295 .\cookbook\views\edit.py:317 msgid "Cannot merge with the same object!" -msgstr "" +msgstr "¡No se puede unir con el mismo objeto!" #: .\cookbook\views\edit.py:311 msgid "Foods merged!" @@ -1939,11 +1822,11 @@ msgstr "¡Alimentos fusionados!" #: .\cookbook\views\import_export.py:42 msgid "Importing is not implemented for this provider" -msgstr "" +msgstr "La importación no está implementada para este proveedor" #: .\cookbook\views\import_export.py:58 msgid "Exporting is not implemented for this provider" -msgstr "" +msgstr "La exportación no está implementada para este proveedor" #: .\cookbook\views\lists.py:42 msgid "Import Log" @@ -1975,7 +1858,7 @@ msgstr "¡Comentario guardado!" #: .\cookbook\views\views.py:152 msgid "This recipe is already linked to the book!" -msgstr "" +msgstr "¡Esta receta ya está enlazada al libro!" #: .\cookbook\views\views.py:158 msgid "Bookmark saved!" @@ -1984,8 +1867,8 @@ msgstr "¡Marcador guardado!" #: .\cookbook\views\views.py:380 msgid "" "The setup page can only be used to create the first user! If you have " -"forgotten your superuser credentials please consult the django documentation " -"on how to reset passwords." +"forgotten your superuser credentials please consult the django documentation" +" on how to reset passwords." msgstr "" "La página de configuración sólo puede ser utilizada para crear el primer " "usuario. Si has olvidado tus credenciales de superusuario, por favor " @@ -2006,157 +1889,3 @@ msgstr "¡Se proporcionó un enlace de invitación con formato incorrecto!" #: .\cookbook\views\views.py:470 msgid "Invite Link not valid or already used!" msgstr "¡El enlace de invitación no es válido o ya se ha utilizado!" - -#~ msgid "Export Base64 encoded image?" -#~ msgstr "¿Exportar imagen codificada en Base64?" - -#~ msgid "Download export directly or show on page?" -#~ msgstr "¿Descargar exportar directamente o mostrar en la página?" - -#~ msgid "Simply paste a JSON export into this textarea and click import." -#~ msgstr "" -#~ "Simplemente pegue una exportación JSON en este área de texto y haga clic " -#~ "en importar." - -#~ msgid "Scaling factor for recipe." -#~ msgstr "Factor de escala para receta." - -#~ msgid "Exported Recipe" -#~ msgstr "Receta exportada" - -#~ msgid "Copy to clipboard" -#~ msgstr "Copiar al portapapeles" - -#~ msgid "Copied!" -#~ msgstr "¡Copiado!" - -#~ msgid "Copy list to clipboard" -#~ msgstr "Copiar lista al portapapeles" - -#~ msgid "Error" -#~ msgstr "Error" - -#~ msgid "There was an error loading the recipe!" -#~ msgstr "¡Hubo un error al cargar la receta!" - -#~ msgid "Updated" -#~ msgstr "Actualizada" - -#~ msgid "Changes saved successfully!" -#~ msgstr "¡Los cambios se guardaron exitosamente!" - -#~ msgid "There was an error updating the recipe!" -#~ msgstr "¡Hubo un error al actualizar la receta!" - -#~ msgid "Are you sure that you want to delete this ingredient?" -#~ msgstr "¿Estás seguro de que quieres eliminar este ingrediente?" - -#~ msgid "Are you sure that you want to delete this step?" -#~ msgstr "¿Estás seguro de que quieres eliminar este paso?" - -#~ msgid "There was an error loading a resource!" -#~ msgstr "¡Hubo un error al cargar un recurso!" - -#~ msgid "Recipe Multiplier" -#~ msgstr "Multiplicador de recetas" - -#~ msgid "" -#~ "When deleting a meal type all entries using that type will be deleted as " -#~ "well. Deletion will apply when configuration is saved. Do you want to " -#~ "proceed?" -#~ msgstr "" -#~ "Al borrar un tipo de comida, todas las entradas que usen ese tipo serán " -#~ "borradas también. El borrado se aplicará cuando se guarde la " -#~ "configuración. ¿Quieres continuar?" - -#~ msgid "Add to Book" -#~ msgstr "Añadir al Libro" - -#~ msgid "Add to Plan" -#~ msgstr "Añadir al menú" - -#~ msgid "Print" -#~ msgstr "Imprimir" - -#~ msgid "Share" -#~ msgstr "Compartir" - -#~ msgid "in" -#~ msgstr "en" - -#~ msgid "Preparation time ~" -#~ msgstr "Tiempo de preparación ~" - -#~ msgid "Minutes" -#~ msgstr "Minutos" - -#~ msgid "View external recipe" -#~ msgstr "Ver receta externa" - -#~ msgid "External recipe image" -#~ msgstr "Imagen de la receta externa" - -#~ msgid "External recipe" -#~ msgstr "Receta externa" - -#~ msgid "" -#~ "\n" -#~ " This is an external recipe, which " -#~ "means you can only view it by opening the link\n" -#~ " above.\n" -#~ " You can convert this recipe to a " -#~ "fancy recipe by pressing the convert button. The\n" -#~ " original\n" -#~ " file\n" -#~ " will still be accessible.\n" -#~ " " -#~ msgstr "" -#~ "\n" -#~ " Esta es una receta externa, lo que " -#~ "significa que sólo puedes verla abriendo el enlace de\n" -#~ " arriba.\n" -#~ " Puedes convertir esta receta en una " -#~ "receta de lujo pulsando el botón de conversión.\n" -#~ " El\n" -#~ " archivo\n" -#~ " seguirá siendo accesible.\n" -#~ " " - -#~ msgid "Convert now!" -#~ msgstr "¡Convertir ahora!" - -#~ msgid "Your username and password didn't match. Please try again." -#~ msgstr "" -#~ "Tu nombre de usuario y contraseña no coinciden. Por favor, inténtelo de " -#~ "nuevo." - -#~ msgid "There was an error updating a resource!" -#~ msgstr "¡Hubo un error al actualizar un recurso!" - -#~ msgid "Object created successfully!" -#~ msgstr "¡Objeto creado con éxito!" - -#~ msgid "Please enter a valid food" -#~ msgstr "Por favor, introduzca un alimento válido" - -#~ msgid "Already importing the selected recipe, please wait!" -#~ msgstr "Ya se está importando la receta seleccionada, ¡por favor espere!" - -#~ msgid "An error occurred while trying to import this recipe!" -#~ msgstr "¡Se produjo un error al intentar importar esta receta!" - -#~ msgid "Recipe imported successfully!" -#~ msgstr "¡Receta importada con éxito!" - -#~ msgid "Something went wrong during the import!" -#~ msgstr "¡Algo salió mal durante la importación!" - -#~ msgid "Could not parse the supplied JSON!" -#~ msgstr "¡No se pudo analizar el JSON proporcionado!" - -#~ msgid "" -#~ "External recipes cannot be exported, please share the file directly or " -#~ "select an internal recipe." -#~ msgstr "" -#~ "Las recetas externas no se pueden exportar, comparta el archivo " -#~ "directamente o seleccione una receta interna." From b552badff76648d412200a42c44271cc706cec57 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 11 Mar 2021 15:37:37 +0100 Subject: [PATCH 54/96] fixed limit random recipe --- cookbook/views/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/views/api.py b/cookbook/views/api.py index fcb02c05..400896a1 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -72,7 +72,7 @@ class StandardFilterMixin(ViewSetMixin): random = self.request.query_params.get('random', False) if limit is not None: if random: - queryset = queryset.order_by("?")[:limit] + queryset = queryset.order_by("?")[:int(limit)] else: queryset = queryset[:int(limit)] return queryset From 7e38e946a5634c7643f05d6317192ab40cd7e9b8 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 11 Mar 2021 16:41:05 +0100 Subject: [PATCH 55/96] fixed various space related bugs --- cookbook/forms.py | 2 +- cookbook/views/data.py | 6 +++--- cookbook/views/edit.py | 4 ++-- cookbook/views/new.py | 3 ++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cookbook/forms.py b/cookbook/forms.py index 73a80417..e80fe32f 100644 --- a/cookbook/forms.py +++ b/cookbook/forms.py @@ -266,7 +266,7 @@ class SyncForm(forms.ModelForm): def __init__(self, *args, **kwargs): space = kwargs.pop('space') super().__init__(*args, **kwargs) - self.fields['book'].queryset = Storage.objects.filter(space=space).all() + self.fields['storage'].queryset = Storage.objects.filter(space=space).all() class Meta: model = Sync diff --git a/cookbook/views/data.py b/cookbook/views/data.py index 39218e6f..1ad355a5 100644 --- a/cookbook/views/data.py +++ b/cookbook/views/data.py @@ -29,7 +29,7 @@ def sync(request): if not has_group_permission(request.user, ['admin']): messages.add_message(request, messages.ERROR, _('You do not have the required permissions to view this page!')) return HttpResponseRedirect(reverse('data_sync')) - form = SyncForm(request.POST) + form = SyncForm(request.POST, space=request.space) if form.is_valid(): new_path = Sync() new_path.path = form.cleaned_data['path'] @@ -39,9 +39,9 @@ def sync(request): new_path.save() return redirect('data_sync') else: - form = SyncForm() + form = SyncForm(space=request.space) - monitored_paths = SyncTable(Sync.objects.fitler(space=request.space).all()) + monitored_paths = SyncTable(Sync.objects.filter(space=request.space).all()) RequestConfig(request, paginate={'per_page': 25}).configure(monitored_paths) return render(request, 'batch/monitor.html', {'form': form, 'monitored_paths': monitored_paths}) diff --git a/cookbook/views/edit.py b/cookbook/views/edit.py index 3ce02087..fd127800 100644 --- a/cookbook/views/edit.py +++ b/cookbook/views/edit.py @@ -279,7 +279,7 @@ def edit_ingredients(request): new_unit = units_form.cleaned_data['new_unit'] old_unit = units_form.cleaned_data['old_unit'] if new_unit != old_unit: - recipe_ingredients = Ingredient.objects.filter(unit=old_unit, space=request.space).all() + recipe_ingredients = Ingredient.objects.filter(unit=old_unit, step__recipe__space=request.space).all() for i in recipe_ingredients: i.unit = new_unit i.save() @@ -295,7 +295,7 @@ def edit_ingredients(request): new_food = food_form.cleaned_data['new_food'] old_food = food_form.cleaned_data['old_food'] if new_food != old_food: - ingredients = Ingredient.objects.filter(food=old_food, space=request.space).all() + ingredients = Ingredient.objects.filter(food=old_food, step__recipe__space=request.space).all() for i in ingredients: i.food = new_food i.save() diff --git a/cookbook/views/new.py b/cookbook/views/new.py index 927c873c..f9c79013 100644 --- a/cookbook/views/new.py +++ b/cookbook/views/new.py @@ -103,7 +103,8 @@ def create_new_external_recipe(request, import_id): recipe.save() - recipe.keywords.set(form.cleaned_data['keywords']) + if form.cleaned_data['keywords']: + recipe.keywords.set(form.cleaned_data['keywords']) new_recipe.delete() From fdcdf6a0264ec7bd02510e547b33e97af3252445 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 11 Mar 2021 18:23:00 +0100 Subject: [PATCH 56/96] added food test --- cookbook/tests/api/test_api_food.py | 69 -------- cookbook/tests/pytest/api/test_api_food.py | 149 ++++++++++++++++++ cookbook/tests/pytest/api/test_api_keyword.py | 6 +- 3 files changed, 152 insertions(+), 72 deletions(-) delete mode 100644 cookbook/tests/api/test_api_food.py create mode 100644 cookbook/tests/pytest/api/test_api_food.py diff --git a/cookbook/tests/api/test_api_food.py b/cookbook/tests/api/test_api_food.py deleted file mode 100644 index 1f0cf519..00000000 --- a/cookbook/tests/api/test_api_food.py +++ /dev/null @@ -1,69 +0,0 @@ -import json - -from cookbook.models import Food -from cookbook.tests.views.test_views import TestViews -from django.urls import reverse - - -class TestApiUnit(TestViews): - - def setUp(self): - super(TestApiUnit, self).setUp() - self.food_1 = Food.objects.create( - name='Beef' - ) - self.food_2 = Food.objects.create( - name='Chicken' - ) - - def test_keyword_list(self): - # verify view permissions are applied accordingly - self.batch_requests( - [ - (self.anonymous_client, 403), - (self.guest_client_1, 403), - (self.user_client_1, 200), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - reverse('api:food-list') - ) - - # verify storage is returned - r = self.user_client_1.get(reverse('api:food-list')) - self.assertEqual(r.status_code, 200) - response = json.loads(r.content) - self.assertEqual(len(response), 2) - self.assertEqual(response[0]['name'], self.food_1.name) - - r = self.user_client_1.get(f'{reverse("api:food-list")}?limit=1') - response = json.loads(r.content) - self.assertEqual(len(response), 1) - - r = self.user_client_1.get(f'{reverse("api:food-list")}?query=Pork') - response = json.loads(r.content) - self.assertEqual(len(response), 0) - - r = self.user_client_1.get(f'{reverse("api:food-list")}?query=Beef') - response = json.loads(r.content) - self.assertEqual(len(response), 1) - - def test_keyword_update(self): - r = self.user_client_1.patch( - reverse( - 'api:food-detail', - args={self.food_1.id} - ), - {'name': 'new'}, - content_type='application/json' - ) - response = json.loads(r.content) - self.assertEqual(r.status_code, 200) - self.assertEqual(response['name'], 'new') - - def test_keyword_delete(self): - r = self.user_client_1.delete( - reverse('api:food-detail', args={self.food_1.id}) - ) - self.assertEqual(r.status_code, 204) - self.assertEqual(Food.objects.count(), 1) diff --git a/cookbook/tests/pytest/api/test_api_food.py b/cookbook/tests/pytest/api/test_api_food.py new file mode 100644 index 00000000..4427eaac --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_food.py @@ -0,0 +1,149 @@ +import json + +import pytest +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import Food + +LIST_URL = 'api:food-list' +DETAIL_URL = 'api:food-detail' + + +@pytest.fixture() +def obj_1(space_1): + return Food.objects.get_or_create(name='test_1', space=space_1)[0] + + +@pytest.fixture +def obj_2(space_1): + return Food.objects.get_or_create(name='test_2', space=space_1)[0] + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 1 + + +def test_list_filter(obj_1, obj_2, u1_s1): + # verify storage is returned + r = u1_s1.get(reverse(LIST_URL)) + assert r.status_code == 200 + response = json.loads(r.content) + assert len(response) == 2 + assert response[0]['name'] == obj_1.name + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content) + assert len(response) == 1 + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query=chicken').content) + assert len(response) == 0 + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query={obj_1.name[4:]}').content) + assert len(response) == 1 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], + ['g1_s2', 403], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'name': 'new'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['name'] == 'new' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_add(arg, request, u1_s2): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'name': 'test'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['name'] == 'test' + r = c.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 200 + r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 + + +def test_add_duplicate(u1_s1, u1_s2, obj_1): + r = u1_s1.post( + reverse(LIST_URL), + {'name': obj_1.name}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == 201 + assert response['id'] == obj_1.id + + r = u1_s2.post( + reverse(LIST_URL), + {'name': obj_1.name}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == 201 + assert response['id'] != obj_1.id + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert Food.objects.count() == 0 diff --git a/cookbook/tests/pytest/api/test_api_keyword.py b/cookbook/tests/pytest/api/test_api_keyword.py index 946e04f5..7319bcf2 100644 --- a/cookbook/tests/pytest/api/test_api_keyword.py +++ b/cookbook/tests/pytest/api/test_api_keyword.py @@ -50,13 +50,13 @@ def test_list_filter(obj_1, obj_2, u1_s1): assert len(response) == 2 assert response[0]['name'] == obj_1.name - response = json.loads(u1_s1.get(f'{reverse("api:keyword-list")}?limit=1').content) + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content) assert len(response) == 1 - response = json.loads(u1_s1.get(f'{reverse("api:keyword-list")}?query=chicken').content) + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query=chicken').content) assert len(response) == 0 - response = json.loads(u1_s1.get(f'{reverse("api:keyword-list")}?query={obj_1.name[4:]}').content) + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query={obj_1.name[4:]}').content) assert len(response) == 1 From d049cf6d3d2881eceb9d6636ab93aae438656136 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 11 Mar 2021 21:50:54 +0100 Subject: [PATCH 57/96] ingredient test finished --- cookbook/tests/api/test_api_ingredient.py | 0 .../tests/pytest/api/test_api_ingredient.py | 106 ++++++++++++++++++ cookbook/tests/pytest/conftest.py | 46 +++++++- 3 files changed, 147 insertions(+), 5 deletions(-) delete mode 100644 cookbook/tests/api/test_api_ingredient.py create mode 100644 cookbook/tests/pytest/api/test_api_ingredient.py diff --git a/cookbook/tests/api/test_api_ingredient.py b/cookbook/tests/api/test_api_ingredient.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/pytest/api/test_api_ingredient.py b/cookbook/tests/pytest/api/test_api_ingredient.py new file mode 100644 index 00000000..2fbacbed --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_ingredient.py @@ -0,0 +1,106 @@ +import json + +import pytest +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import Food, Ingredient + +LIST_URL = 'api:ingredient-list' +DETAIL_URL = 'api:ingredient-detail' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(recipe_1_s1, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 10 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + with scopes_disabled(): + recipe_1_s1.space = space_2 + recipe_1_s1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 0 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 10 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], + ['g1_s2', 403], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, recipe_1_s1): + with scopes_disabled(): + i = recipe_1_s1.steps.first().ingredients.first() + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={i.id} + ), + {'note': 'new'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['note'] == 'new' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_add(arg, request, u1_s2): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'food': {'name': 'test'}, 'unit': {'name': 'test'}, 'amount': 1}, + content_type='application/json' + ) + response = json.loads(r.content) + print(r) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['id'] == 1 + r = c.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 # ingredient is not linked to a recipe and therefore cannot be accessed + r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 + + +def test_delete(u1_s1, u1_s2, recipe_1_s1): + with scopes_disabled(): + i = recipe_1_s1.steps.first().ingredients.first() + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={i.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={i.id} + ) + ) + + assert r.status_code == 204 + assert not Ingredient.objects.filter(pk=i.id).exists() diff --git a/cookbook/tests/pytest/conftest.py b/cookbook/tests/pytest/conftest.py index 75f0bb38..c9ffc423 100644 --- a/cookbook/tests/pytest/conftest.py +++ b/cookbook/tests/pytest/conftest.py @@ -7,7 +7,7 @@ from django.contrib import auth from django.contrib.auth.models import User, Group from django_scopes import scopes_disabled -from cookbook.models import Space, Recipe +from cookbook.models import Space, Recipe, Step, Ingredient, Food, Unit # hack from https://github.com/raphaelm/django-scopes to disable scopes for all fixtures @@ -40,10 +40,9 @@ def space_2(): # ---------------------- OBJECT FIXTURES --------------------- -@pytest.fixture() -def recipe_1_s1(space_1, u1_s1): - return Recipe.objects.create( - name='recipe_1_s1', +def get_random_recipe(space_1, u1_s1): + r = Recipe.objects.create( + name=uuid.uuid4(), waiting_time=20, working_time=20, servings=4, @@ -51,6 +50,43 @@ def recipe_1_s1(space_1, u1_s1): space=space_1 ) + s1 = Step.objects.create(name=uuid.uuid4(), instruction=uuid.uuid4(), ) + s2 = Step.objects.create(name=uuid.uuid4(), instruction=uuid.uuid4(), ) + + r.steps.add(s1) + r.steps.add(s2) + + for x in range(5): + s1.ingredients.add( + Ingredient.objects.create( + amount=1, + food=Food.objects.create(name=uuid.uuid4(), space=space_1,), + unit=Unit.objects.create(name=uuid.uuid4(), space=space_1,), + note=uuid.uuid4(), + ) + ) + + s2.ingredients.add( + Ingredient.objects.create( + amount=1, + food=Food.objects.create(name=uuid.uuid4(), space=space_1,), + unit=Unit.objects.create(name=uuid.uuid4(), space=space_1,), + note=uuid.uuid4(), + ) + ) + + return r + + +@pytest.fixture +def recipe_1_s1(space_1, u1_s1): + return get_random_recipe(space_1, u1_s1) + + +@pytest.fixture +def recipe_2_s1(space_1, u1_s1): + return get_random_recipe(space_1, u1_s1) + # ---------------------- USER FIXTURES ----------------------- # maybe better with factories but this is very explict so ... From d7402f60c5cdac5ac21fbaa897152a64df05a4a0 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Fri, 12 Mar 2021 09:44:16 +0100 Subject: [PATCH 58/96] meal plan api tests --- cookbook/models.py | 8 +- cookbook/serializer.py | 12 +- cookbook/tests/api/test_api_meal_plan.py | 0 cookbook/tests/api/test_api_meal_type.py | 0 .../tests/pytest/api/test_api_meal_plan.py | 134 ++++++++++++++++++ .../tests/pytest/api/test_api_meal_type.py | 132 +++++++++++++++++ 6 files changed, 279 insertions(+), 7 deletions(-) delete mode 100644 cookbook/tests/api/test_api_meal_plan.py delete mode 100644 cookbook/tests/api/test_api_meal_type.py create mode 100644 cookbook/tests/pytest/api/test_api_meal_plan.py create mode 100644 cookbook/tests/pytest/api/test_api_meal_type.py diff --git a/cookbook/models.py b/cookbook/models.py index e89e7745..cd335f7c 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -459,15 +459,11 @@ class MealType(models.Model, PermissionModelMixin): class MealPlan(models.Model, PermissionModelMixin): - recipe = models.ForeignKey( - Recipe, on_delete=models.CASCADE, blank=True, null=True - ) + recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, blank=True, null=True) servings = models.DecimalField(default=1, max_digits=8, decimal_places=4) title = models.CharField(max_length=64, blank=True, default='') created_by = models.ForeignKey(User, on_delete=models.CASCADE) - shared = models.ManyToManyField( - User, blank=True, related_name='plan_share' - ) + shared = models.ManyToManyField(User, blank=True, related_name='plan_share') meal_type = models.ForeignKey(MealType, on_delete=models.CASCADE) note = models.TextField(blank=True) date = models.DateField() diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 60a601f0..f736538b 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -47,10 +47,15 @@ class SpacedModelSerializer(serializers.ModelSerializer): class MealTypeSerializer(SpacedModelSerializer): + + def create(self, validated_data): + validated_data['created_by'] = self.context['request'].user + return super().create(validated_data) + class Meta: model = MealType fields = ('id', 'name', 'order', 'created_by') - read_only_fields = ('space',) + read_only_fields = ('created_by',) class UserNameSerializer(WritableNestedModelSerializer): @@ -303,6 +308,10 @@ class MealPlanSerializer(SpacedModelSerializer): def get_note_markdown(self, obj): return markdown(obj.note) + def create(self, validated_data): + validated_data['created_by'] = self.context['request'].user + return super().create(validated_data) + class Meta: model = MealPlan fields = ( @@ -310,6 +319,7 @@ class MealPlanSerializer(SpacedModelSerializer): 'date', 'meal_type', 'created_by', 'shared', 'recipe_name', 'meal_type_name' ) + read_only_fields = ('created_by',) class ShoppingListRecipeSerializer(SpacedModelSerializer): diff --git a/cookbook/tests/api/test_api_meal_plan.py b/cookbook/tests/api/test_api_meal_plan.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/api/test_api_meal_type.py b/cookbook/tests/api/test_api_meal_type.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/pytest/api/test_api_meal_plan.py b/cookbook/tests/pytest/api/test_api_meal_plan.py new file mode 100644 index 00000000..a5227112 --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_meal_plan.py @@ -0,0 +1,134 @@ +import json +from datetime import datetime, timedelta + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import Food, MealPlan, MealType + +LIST_URL = 'api:mealplan-list' +DETAIL_URL = 'api:mealplan-detail' + + +@pytest.fixture() +def meal_type(space_1, u1_s1): + return MealType.objects.get_or_create(name='test', space=space_1, created_by=auth.get_user(u1_s1))[0] + + +@pytest.fixture() +def obj_1(space_1, recipe_1_s1, meal_type, u1_s1): + return MealPlan.objects.create(recipe=recipe_1_s1, space=space_1, meal_type=meal_type, date=datetime.now(), created_by=auth.get_user(u1_s1)) + + +@pytest.fixture +def obj_2(space_1, recipe_1_s1, meal_type, u1_s1): + return MealPlan.objects.create(recipe=recipe_1_s1, space=space_1, meal_type=meal_type, date=datetime.now(), created_by=auth.get_user(u1_s1)) + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + +def test_list_filter(obj_1, u1_s1): + r = u1_s1.get(reverse(LIST_URL)) + assert r.status_code == 200 + response = json.loads(r.content) + assert len(response) == 1 + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?from_date={(datetime.now() + timedelta(days=2)).strftime("%Y-%m-%d")}').content) + assert len(response) == 0 + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?to_date={(datetime.now() - timedelta(days=2)).strftime("%Y-%m-%d")}').content) + assert len(response) == 0 + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?from_date={(datetime.now() - timedelta(days=2)).strftime("%Y-%m-%d")}&to_date={(datetime.now() + timedelta(days=2)).strftime("%Y-%m-%d")}').content) + assert len(response) == 1 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 404], + ['u1_s1', 200], + ['a1_s1', 404], + ['g1_s2', 404], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'title': 'new'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['title'] == 'new' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 201], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_add(arg, request, u1_s2, recipe_1_s1, meal_type): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'recipe': recipe_1_s1.id, 'meal_type': meal_type.id, 'date': (datetime.now()).strftime("%Y-%m-%d"), 'servings': 1, 'title': 'test'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['title'] == 'test' + r = c.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 200 + r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert MealPlan.objects.count() == 0 diff --git a/cookbook/tests/pytest/api/test_api_meal_type.py b/cookbook/tests/pytest/api/test_api_meal_type.py new file mode 100644 index 00000000..61fae730 --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_meal_type.py @@ -0,0 +1,132 @@ +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import Food, MealType + +LIST_URL = 'api:mealtype-list' +DETAIL_URL = 'api:mealtype-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1): + return MealType.objects.get_or_create(name='test_1', created_by=auth.get_user(u1_s1), space=space_1)[0] + + +@pytest.fixture +def obj_2(space_1, u1_s1): + return MealType.objects.get_or_create(name='test_2', created_by=auth.get_user(u1_s1), space=space_1)[0] + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], + ['g1_s2', 403], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'name': 'new'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['name'] == 'new' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 201], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_add(arg, request, u1_s2): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'name': 'test'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['name'] == 'test' + r = c.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 200 + r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 + +# TODO make name in space unique +# def test_add_duplicate(u1_s1, u1_s2, obj_1): +# r = u1_s1.post( +# reverse(LIST_URL), +# {'name': obj_1.name}, +# content_type='application/json' +# ) +# response = json.loads(r.content) +# assert r.status_code == 201 +# assert response['id'] == obj_1.id +# +# r = u1_s2.post( +# reverse(LIST_URL), +# {'name': obj_1.name}, +# content_type='application/json' +# ) +# response = json.loads(r.content) +# assert r.status_code == 201 +# assert response['id'] != obj_1.id + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert Food.objects.count() == 0 From a7b7272beca450faccb1c3a5c423a376a6464dc3 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Fri, 12 Mar 2021 09:50:20 +0100 Subject: [PATCH 59/96] view log api test --- cookbook/tests/api/test_api_view_log.py | 0 .../tests/pytest/api/test_api_view_log.py | 113 ++++++++++++++++++ cookbook/views/api.py | 6 +- 3 files changed, 118 insertions(+), 1 deletion(-) delete mode 100644 cookbook/tests/api/test_api_view_log.py create mode 100644 cookbook/tests/pytest/api/test_api_view_log.py diff --git a/cookbook/tests/api/test_api_view_log.py b/cookbook/tests/api/test_api_view_log.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/pytest/api/test_api_view_log.py b/cookbook/tests/pytest/api/test_api_view_log.py new file mode 100644 index 00000000..334daa03 --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_view_log.py @@ -0,0 +1,113 @@ +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import Keyword, CookLog, ViewLog + +LIST_URL = 'api:viewlog-list' +DETAIL_URL = 'api:viewlog-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1, recipe_1_s1): + return ViewLog.objects.create(recipe=recipe_1_s1, created_by=auth.get_user(u1_s1), space=space_1) + + +@pytest.fixture +def obj_2(space_1, u1_s1, recipe_1_s1): + return ViewLog.objects.create(recipe=recipe_1_s1, created_by=auth.get_user(u1_s1), space=space_1) + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 404], + ['u1_s1', 200], + ['a1_s1', 404], + ['g1_s2', 404], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'servings': 2}, + content_type='application/json' + ) + assert r.status_code == arg[1] + + +# TODO disabled until https://github.com/vabene1111/recipes/issues/484 + +# @pytest.mark.parametrize("arg", [ +# ['a_u', 403], +# ['g1_s1', 201], +# ['u1_s1', 201], +# ['a1_s1', 201], +# ]) +# def test_add(arg, request, u1_s2, u2_s1, recipe_1_s1): +# c = request.getfixturevalue(arg[0]) +# r = c.post( +# reverse(LIST_URL), +# {'recipe': recipe_1_s1.id}, +# content_type='application/json' +# ) +# response = json.loads(r.content) +# assert r.status_code == arg[1] +# if r.status_code == 201: +# assert response['recipe'] == recipe_1_s1.id +# r = c.get(reverse(DETAIL_URL, args={response['id']})) +# assert r.status_code == 200 +# r = u2_s1.get(reverse(DETAIL_URL, args={response['id']})) +# assert r.status_code == 404 +# r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) +# assert r.status_code == 404 + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert ViewLog.objects.count() == 0 diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 400896a1..884f0e1e 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -382,7 +382,11 @@ class ViewLogViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsOwner] def get_queryset(self): - return self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all()[:5] + self.queryset = self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all() + if self.request.method == 'GET': + return self.queryset[:5] + else: + return self.queryset class CookLogViewSet(viewsets.ModelViewSet): From e8f7caebd1b303a1ffc1dee06c207dcac14cf3f8 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Fri, 12 Mar 2021 09:52:46 +0100 Subject: [PATCH 60/96] test unit api --- cookbook/tests/api/test_api_unit.py | 69 ---------- cookbook/tests/pytest/api/test_api_unit.py | 149 +++++++++++++++++++++ 2 files changed, 149 insertions(+), 69 deletions(-) delete mode 100644 cookbook/tests/api/test_api_unit.py create mode 100644 cookbook/tests/pytest/api/test_api_unit.py diff --git a/cookbook/tests/api/test_api_unit.py b/cookbook/tests/api/test_api_unit.py deleted file mode 100644 index e21a4f34..00000000 --- a/cookbook/tests/api/test_api_unit.py +++ /dev/null @@ -1,69 +0,0 @@ -import json - -from cookbook.models import Unit -from cookbook.tests.views.test_views import TestViews -from django.urls import reverse - - -class TestApiUnit(TestViews): - - def setUp(self): - super(TestApiUnit, self).setUp() - self.unit_1 = Unit.objects.create( - name='kg' - ) - self.unit_2 = Unit.objects.create( - name='g' - ) - - def test_keyword_list(self): - # verify view permissions are applied accordingly - self.batch_requests( - [ - (self.anonymous_client, 403), - (self.guest_client_1, 403), - (self.user_client_1, 200), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - reverse('api:unit-list') - ) - - # verify storage is returned - r = self.user_client_1.get(reverse('api:unit-list')) - self.assertEqual(r.status_code, 200) - response = json.loads(r.content) - self.assertEqual(len(response), 2) - self.assertEqual(response[0]['name'], self.unit_1.name) - - r = self.user_client_1.get(f'{reverse("api:unit-list")}?limit=1') - response = json.loads(r.content) - self.assertEqual(len(response), 1) - - r = self.user_client_1.get(f'{reverse("api:unit-list")}?query=m') - response = json.loads(r.content) - self.assertEqual(len(response), 0) - - r = self.user_client_1.get(f'{reverse("api:unit-list")}?query=kg') - response = json.loads(r.content) - self.assertEqual(len(response), 1) - - def test_keyword_update(self): - r = self.user_client_1.patch( - reverse( - 'api:unit-detail', - args={self.unit_1.id} - ), - {'name': 'new'}, - content_type='application/json' - ) - response = json.loads(r.content) - self.assertEqual(r.status_code, 200) - self.assertEqual(response['name'], 'new') - - def test_keyword_delete(self): - r = self.user_client_1.delete( - reverse('api:unit-detail', args={self.unit_1.id}) - ) - self.assertEqual(r.status_code, 204) - self.assertEqual(Unit.objects.count(), 1) diff --git a/cookbook/tests/pytest/api/test_api_unit.py b/cookbook/tests/pytest/api/test_api_unit.py new file mode 100644 index 00000000..8e35a427 --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_unit.py @@ -0,0 +1,149 @@ +import json + +import pytest +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import Food, Unit + +LIST_URL = 'api:unit-list' +DETAIL_URL = 'api:unit-detail' + + +@pytest.fixture() +def obj_1(space_1): + return Unit.objects.get_or_create(name='test_1', space=space_1)[0] + + +@pytest.fixture +def obj_2(space_1): + return Unit.objects.get_or_create(name='test_2', space=space_1)[0] + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 1 + + +def test_list_filter(obj_1, obj_2, u1_s1): + # verify storage is returned + r = u1_s1.get(reverse(LIST_URL)) + assert r.status_code == 200 + response = json.loads(r.content) + assert len(response) == 2 + assert response[0]['name'] == obj_1.name + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content) + assert len(response) == 1 + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query=chicken').content) + assert len(response) == 0 + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query={obj_1.name[4:]}').content) + assert len(response) == 1 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], + ['g1_s2', 403], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'name': 'new'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['name'] == 'new' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_add(arg, request, u1_s2): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'name': 'test'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['name'] == 'test' + r = c.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 200 + r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 + + +def test_add_duplicate(u1_s1, u1_s2, obj_1): + r = u1_s1.post( + reverse(LIST_URL), + {'name': obj_1.name}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == 201 + assert response['id'] == obj_1.id + + r = u1_s2.post( + reverse(LIST_URL), + {'name': obj_1.name}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == 201 + assert response['id'] != obj_1.id + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert Food.objects.count() == 0 From d767743b6495543d9cbfc936bc26c28de5986397 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Fri, 12 Mar 2021 10:16:51 +0100 Subject: [PATCH 61/96] user name api test --- cookbook/tests/api/test_api_username.py | 41 ----------- cookbook/tests/pytest/api/test_api_food.py | 1 - cookbook/tests/pytest/api/test_api_keyword.py | 1 - cookbook/tests/pytest/api/test_api_unit.py | 1 - .../tests/pytest/api/test_api_username.py | 70 +++++++++++++++++++ cookbook/views/api.py | 4 +- 6 files changed, 71 insertions(+), 47 deletions(-) delete mode 100644 cookbook/tests/api/test_api_username.py create mode 100644 cookbook/tests/pytest/api/test_api_username.py diff --git a/cookbook/tests/api/test_api_username.py b/cookbook/tests/api/test_api_username.py deleted file mode 100644 index 23657ece..00000000 --- a/cookbook/tests/api/test_api_username.py +++ /dev/null @@ -1,41 +0,0 @@ -from cookbook.tests.views.test_views import TestViews -from django.contrib import auth -from django.urls import reverse - - -class TestApiUsername(TestViews): - - def setUp(self): - super(TestApiUsername, self).setUp() - - def test_forbidden_methods(self): - r = self.user_client_1.post( - reverse('api:username-list')) - self.assertEqual(r.status_code, 405) - - r = self.user_client_1.put( - reverse( - 'api:username-detail', - args=[auth.get_user(self.user_client_1).pk]) - ) - self.assertEqual(r.status_code, 405) - - r = self.user_client_1.delete( - reverse( - 'api:username-detail', - args=[auth.get_user(self.user_client_1).pk] - ) - ) - self.assertEqual(r.status_code, 405) - - def test_username_list(self): - self.batch_requests( - [ - (self.anonymous_client, 403), - (self.guest_client_1, 200), - (self.user_client_1, 200), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - reverse('api:username-list') - ) diff --git a/cookbook/tests/pytest/api/test_api_food.py b/cookbook/tests/pytest/api/test_api_food.py index 4427eaac..6619d8b3 100644 --- a/cookbook/tests/pytest/api/test_api_food.py +++ b/cookbook/tests/pytest/api/test_api_food.py @@ -43,7 +43,6 @@ def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): def test_list_filter(obj_1, obj_2, u1_s1): - # verify storage is returned r = u1_s1.get(reverse(LIST_URL)) assert r.status_code == 200 response = json.loads(r.content) diff --git a/cookbook/tests/pytest/api/test_api_keyword.py b/cookbook/tests/pytest/api/test_api_keyword.py index 7319bcf2..650ac14c 100644 --- a/cookbook/tests/pytest/api/test_api_keyword.py +++ b/cookbook/tests/pytest/api/test_api_keyword.py @@ -43,7 +43,6 @@ def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): def test_list_filter(obj_1, obj_2, u1_s1): - # verify storage is returned r = u1_s1.get(reverse(LIST_URL)) assert r.status_code == 200 response = json.loads(r.content) diff --git a/cookbook/tests/pytest/api/test_api_unit.py b/cookbook/tests/pytest/api/test_api_unit.py index 8e35a427..f0a131ed 100644 --- a/cookbook/tests/pytest/api/test_api_unit.py +++ b/cookbook/tests/pytest/api/test_api_unit.py @@ -43,7 +43,6 @@ def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): def test_list_filter(obj_1, obj_2, u1_s1): - # verify storage is returned r = u1_s1.get(reverse(LIST_URL)) assert r.status_code == 200 response = json.loads(r.content) diff --git a/cookbook/tests/pytest/api/test_api_username.py b/cookbook/tests/pytest/api/test_api_username.py new file mode 100644 index 00000000..0e4b137d --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_username.py @@ -0,0 +1,70 @@ +import json + +import pytest + +from cookbook.tests.views.test_views import TestViews +from django.contrib import auth +from django.urls import reverse + +LIST_URL = 'api:username-list' +DETAIL_URL = 'api:username-detail' + + +def test_forbidden_methods(u1_s1): + r = u1_s1.post( + reverse(LIST_URL)) + assert r.status_code == 405 + + r = u1_s1.put( + reverse( + DETAIL_URL, + args=[auth.get_user(u1_s1).pk]) + ) + assert r.status_code == 405 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args=[auth.get_user(u1_s1).pk] + ) + ) + assert r.status_code == 405 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_filter(u1_s1, u2_s1, u1_s2, u2_s2): + r = u1_s1.get(reverse(LIST_URL)) + assert r.status_code == 200 + response = json.loads(r.content) + assert len(response) == 2 + + obj_u2_s1 = auth.get_user(u2_s1) + obj_u2_s2 = auth.get_user(u2_s2) + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?filter_list=[{obj_u2_s1.pk},{obj_u2_s2.pk}]').content) + assert len(response) == 1 + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?filter_list=[]').content) + assert len(response) == 0 + + +def test_list_space(u1_s1, u2_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 1 + + u = auth.get_user(u2_s1) + u.userpreference.space = space_2 + u.userpreference.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 2 diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 884f0e1e..5ede3fb2 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -97,9 +97,7 @@ class UserNameViewSet(viewsets.ReadOnlyModelViewSet): if filter_list is not None: queryset = queryset.filter(pk__in=json.loads(filter_list)) except ValueError: - raise APIException( - _('Parameter filter_list incorrectly formatted') - ) + raise APIException(_('Parameter filter_list incorrectly formatted')) return queryset From 3b0413c30ecfe176ed669f764c5ffadb8bf07f51 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Fri, 12 Mar 2021 10:50:08 +0100 Subject: [PATCH 62/96] add test for recipe book --- cookbook/serializer.py | 7 +- cookbook/tests/api/test_api_recipe_book.py | 0 .../tests/pytest/api/test_api_recipe_book.py | 129 ++++++++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) delete mode 100644 cookbook/tests/api/test_api_recipe_book.py create mode 100644 cookbook/tests/pytest/api/test_api_recipe_book.py diff --git a/cookbook/serializer.py b/cookbook/serializer.py index f736538b..c874292b 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -287,9 +287,14 @@ class CommentSerializer(serializers.ModelSerializer): class RecipeBookSerializer(SpacedModelSerializer): + + def create(self, validated_data): + validated_data['created_by'] = self.context['request'].user + return super().create(validated_data) + class Meta: model = RecipeBook - fields = '__all__' + fields = ('id', 'name', 'description', 'icon', 'shared', 'created_by') read_only_fields = ['id', 'created_by'] diff --git a/cookbook/tests/api/test_api_recipe_book.py b/cookbook/tests/api/test_api_recipe_book.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/pytest/api/test_api_recipe_book.py b/cookbook/tests/pytest/api/test_api_recipe_book.py new file mode 100644 index 00000000..19a5ecb0 --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_recipe_book.py @@ -0,0 +1,129 @@ +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import Keyword, RecipeBook + +LIST_URL = 'api:recipebook-list' +DETAIL_URL = 'api:recipebook-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1): + return RecipeBook.objects.get_or_create(name='test_1', created_by=auth.get_user(u1_s1), space=space_1)[0] + + +@pytest.fixture +def obj_2(space_1, u1_s1): + return RecipeBook.objects.get_or_create(name='test_2', created_by=auth.get_user(u1_s1), space=space_1)[0] + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + +def test_list_filter(obj_1, obj_2, u1_s1): + r = u1_s1.get(reverse(LIST_URL)) + assert r.status_code == 200 + response = json.loads(r.content) + assert len(response) == 2 + assert response[0]['name'] == obj_1.name + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content) + assert len(response) == 1 + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query=chicken').content) + assert len(response) == 0 + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query={obj_1.name[4:]}').content) + assert len(response) == 1 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 404], + ['u1_s1', 200], + ['a1_s1', 404], + ['g1_s2', 404], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'name': 'new'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['name'] == 'new' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 201], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_add(arg, request, u1_s2): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'name': 'test'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['name'] == 'test' + r = c.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 200 + r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert Keyword.objects.count() == 0 From a8a132e2a171ea48031b979e9c135b0c9be93a04 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Fri, 12 Mar 2021 12:33:20 +0100 Subject: [PATCH 63/96] fixed recipe book entry api and added test --- cookbook/serializer.py | 13 +- .../tests/api/test_api_recipe_book_entry.py | 0 .../tests/pytest/api/test_api_recipe_book.py | 4 +- .../pytest/api/test_api_recipe_book_entry.py | 124 ++++++++++++++++++ cookbook/views/api.py | 2 +- 5 files changed, 137 insertions(+), 6 deletions(-) delete mode 100644 cookbook/tests/api/test_api_recipe_book_entry.py create mode 100644 cookbook/tests/pytest/api/test_api_recipe_book_entry.py diff --git a/cookbook/serializer.py b/cookbook/serializer.py index c874292b..065c5c85 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -4,7 +4,7 @@ from django.contrib.auth.models import User from drf_writable_nested import (UniqueFieldsMixin, WritableNestedModelSerializer) from rest_framework import serializers -from rest_framework.exceptions import ValidationError +from rest_framework.exceptions import ValidationError, NotAuthenticated, NotFound from rest_framework.serializers import BaseSerializer, Serializer from cookbook.models import (Comment, CookLog, Food, Ingredient, Keyword, @@ -295,13 +295,20 @@ class RecipeBookSerializer(SpacedModelSerializer): class Meta: model = RecipeBook fields = ('id', 'name', 'description', 'icon', 'shared', 'created_by') - read_only_fields = ['id', 'created_by'] class RecipeBookEntrySerializer(serializers.ModelSerializer): + + def validate(self, data): + book = data['book'] + if book.get_owner() == self.context['request'].user: + return data + else: + raise NotFound(detail=None, code=None) + class Meta: model = RecipeBookEntry - fields = '__all__' + fields = ('id', 'book', 'recipe',) class MealPlanSerializer(SpacedModelSerializer): diff --git a/cookbook/tests/api/test_api_recipe_book_entry.py b/cookbook/tests/api/test_api_recipe_book_entry.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/pytest/api/test_api_recipe_book.py b/cookbook/tests/pytest/api/test_api_recipe_book.py index 19a5ecb0..cbf93fe8 100644 --- a/cookbook/tests/pytest/api/test_api_recipe_book.py +++ b/cookbook/tests/pytest/api/test_api_recipe_book.py @@ -5,7 +5,7 @@ from django.contrib import auth from django.urls import reverse from django_scopes import scopes_disabled -from cookbook.models import Keyword, RecipeBook +from cookbook.models import RecipeBook LIST_URL = 'api:recipebook-list' DETAIL_URL = 'api:recipebook-detail' @@ -126,4 +126,4 @@ def test_delete(u1_s1, u1_s2, obj_1): assert r.status_code == 204 with scopes_disabled(): - assert Keyword.objects.count() == 0 + assert RecipeBook.objects.count() == 0 diff --git a/cookbook/tests/pytest/api/test_api_recipe_book_entry.py b/cookbook/tests/pytest/api/test_api_recipe_book_entry.py new file mode 100644 index 00000000..89bf2ba0 --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_recipe_book_entry.py @@ -0,0 +1,124 @@ +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import RecipeBook, RecipeBookEntry + +LIST_URL = 'api:recipebookentry-list' +DETAIL_URL = 'api:recipebookentry-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1, recipe_1_s1): + b = RecipeBook.objects.create(name='test_1', created_by=auth.get_user(u1_s1), space=space_1) + + return RecipeBookEntry.objects.create(book=b, recipe=recipe_1_s1) + + +@pytest.fixture +def obj_2(space_1, u1_s1, recipe_1_s1): + b = RecipeBook.objects.create(name='test_1', created_by=auth.get_user(u1_s1), space=space_1) + return RecipeBookEntry.objects.create(book=b, recipe=recipe_1_s1) + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.book.space = space_2 + obj_1.book.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 404], + ['u1_s1', 200], + ['a1_s1', 404], + ['g1_s2', 404], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1, recipe_2_s1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'recipe': recipe_2_s1.pk}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['recipe'] == recipe_2_s1.pk + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 404], + ['u1_s1', 201], + ['a1_s1', 404], +]) +def test_add(arg, request, u1_s2, obj_1, recipe_2_s1): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'book': obj_1.book.pk, 'recipe': recipe_2_s1.pk}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['recipe'] == recipe_2_s1.pk + r = c.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 200 + r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 + + +def test_add_duplicate(u1_s1, obj_1): + r = u1_s1.post( + reverse(LIST_URL), + {'book': obj_1.book.pk, 'recipe': obj_1.recipe.pk}, + content_type='application/json' + ) + assert r.status_code == 400 + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert RecipeBookEntry.objects.count() == 0 diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 5ede3fb2..678fb672 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -208,7 +208,7 @@ class RecipeBookEntryViewSet(viewsets.ModelViewSet, viewsets.GenericViewSet): permission_classes = [CustomIsOwner] def get_queryset(self): - return self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space) + return self.queryset.filter(book__created_by=self.request.user).filter(book__space=self.request.user.userpreference.space) class MealPlanViewSet(viewsets.ModelViewSet): From 4d6d84bf5b9dd12c62f3f18c1900ef2e9973817e Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Tue, 16 Mar 2021 23:46:54 +0100 Subject: [PATCH 64/96] fixed some tests + added user pref tests --- cookbook/serializer.py | 20 ++- cookbook/tests/api/test_api_userpreference.py | 149 ------------------ .../tests/pytest/api/test_api_meal_type.py | 6 +- .../tests/pytest/api/test_api_recipe_book.py | 1 + .../pytest/api/test_api_userpreference.py | 118 ++++++++++++++ cookbook/views/api.py | 11 +- 6 files changed, 138 insertions(+), 167 deletions(-) delete mode 100644 cookbook/tests/api/test_api_userpreference.py create mode 100644 cookbook/tests/pytest/api/test_api_userpreference.py diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 065c5c85..1b8bcc38 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -4,7 +4,8 @@ from django.contrib.auth.models import User from drf_writable_nested import (UniqueFieldsMixin, WritableNestedModelSerializer) from rest_framework import serializers -from rest_framework.exceptions import ValidationError, NotAuthenticated, NotFound +from rest_framework.exceptions import ValidationError, NotAuthenticated, NotFound, ParseError +from rest_framework.fields import ModelField from rest_framework.serializers import BaseSerializer, Serializer from cookbook.models import (Comment, CookLog, Food, Ingredient, Keyword, @@ -70,6 +71,12 @@ class UserNameSerializer(WritableNestedModelSerializer): class UserPreferenceSerializer(serializers.ModelSerializer): + + def create(self, validated_data): + if validated_data['user'] != self.context['request'].user: + raise NotFound() + return super().create(validated_data) + class Meta: model = UserPreference fields = ( @@ -77,7 +84,6 @@ class UserPreferenceSerializer(serializers.ModelSerializer): 'search_style', 'show_recent', 'plan_share', 'ingredient_decimals', 'comments' ) - read_only_fields = ['user'] class StorageSerializer(SpacedModelSerializer): @@ -295,16 +301,16 @@ class RecipeBookSerializer(SpacedModelSerializer): class Meta: model = RecipeBook fields = ('id', 'name', 'description', 'icon', 'shared', 'created_by') + read_only_fields = ('created_by',) class RecipeBookEntrySerializer(serializers.ModelSerializer): - def validate(self, data): - book = data['book'] - if book.get_owner() == self.context['request'].user: - return data - else: + def create(self, validated_data): + book = validated_data['book'] + if not book.get_owner() == self.context['request'].user: raise NotFound(detail=None, code=None) + return super().create(validated_data) class Meta: model = RecipeBookEntry diff --git a/cookbook/tests/api/test_api_userpreference.py b/cookbook/tests/api/test_api_userpreference.py deleted file mode 100644 index 7e8d051a..00000000 --- a/cookbook/tests/api/test_api_userpreference.py +++ /dev/null @@ -1,149 +0,0 @@ -import json - -from cookbook.models import UserPreference -from cookbook.tests.views.test_views import TestViews -from django.contrib import auth -from django.urls import reverse - - -class TestApiUserPreference(TestViews): - - def setUp(self): - super(TestApiUserPreference, self).setUp() - - def test_preference_create(self): - r = self.user_client_1.post(reverse('api:userpreference-list')) - self.assertEqual(r.status_code, 201) - response = json.loads(r.content) - self.assertEqual( - response['user'], auth.get_user(self.user_client_1).id - ) - self.assertEqual( - response['theme'], - UserPreference._meta.get_field('theme').get_default() - ) - - def test_preference_list(self): - UserPreference.objects.create(user=auth.get_user(self.user_client_1)) - UserPreference.objects.create(user=auth.get_user(self.guest_client_1)) - - # users can only see own preference in list - r = self.user_client_1.get(reverse('api:userpreference-list')) - self.assertEqual(r.status_code, 200) - response = json.loads(r.content) - self.assertEqual(len(response), 1) - self.assertEqual( - response[0]['user'], auth.get_user(self.user_client_1).id - ) - - # superusers can see all user prefs in list - r = self.superuser_client.get(reverse('api:userpreference-list')) - self.assertEqual(r.status_code, 200) - response = json.loads(r.content) - self.assertEqual(len(response), 2) - - def test_preference_retrieve(self): - UserPreference.objects.create(user=auth.get_user(self.user_client_1)) - UserPreference.objects.create(user=auth.get_user(self.guest_client_1)) - - self.batch_requests( - [ - (self.guest_client_1, 404), - (self.user_client_1, 200), - (self.user_client_2, 404), - (self.anonymous_client, 403), - (self.admin_client_1, 404), - (self.superuser_client, 200) - ], - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ) - ) - - def test_preference_update(self): - UserPreference.objects.create(user=auth.get_user(self.user_client_1)) - UserPreference.objects.create(user=auth.get_user(self.guest_client_1)) - - # can update users preference - r = self.user_client_1.put( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ), - {'theme': UserPreference.DARKLY}, - content_type='application/json' - ) - response = json.loads(r.content) - self.assertEqual(r.status_code, 200) - self.assertEqual(response['theme'], UserPreference.DARKLY) - - # cant set another users non existent pref - r = self.user_client_1.put( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_2).id} - ), - {'theme': UserPreference.DARKLY}, - content_type='application/json' - ) - self.assertEqual(r.status_code, 404) - - # cant set another users existent pref - r = self.user_client_2.put( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ), - {'theme': UserPreference.FLATLY}, - content_type='application/json' - ) - self.assertEqual(r.status_code, 404) - - # can set pref as superuser - r = self.superuser_client.put( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ), - {'theme': UserPreference.FLATLY}, - content_type='application/json' - ) - self.assertEqual(r.status_code, 200) - - def test_preference_delete(self): - UserPreference.objects.create(user=auth.get_user(self.user_client_1)) - - # can delete own preference - r = self.user_client_1.delete( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ) - ) - self.assertEqual(r.status_code, 204) - self.assertEqual(UserPreference.objects.count(), 0) - - UserPreference.objects.create(user=auth.get_user(self.user_client_1 - ) - ) - - # cant delete other preference - r = self.user_client_2.delete( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ) - ) - self.assertEqual(r.status_code, 404) - self.assertEqual(UserPreference.objects.count(), 1) - - # superuser can delete everything - r = self.superuser_client.delete( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ) - ) - self.assertEqual(r.status_code, 204) - self.assertEqual(UserPreference.objects.count(), 0) diff --git a/cookbook/tests/pytest/api/test_api_meal_type.py b/cookbook/tests/pytest/api/test_api_meal_type.py index 61fae730..17e0a7ea 100644 --- a/cookbook/tests/pytest/api/test_api_meal_type.py +++ b/cookbook/tests/pytest/api/test_api_meal_type.py @@ -45,10 +45,10 @@ def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): @pytest.mark.parametrize("arg", [ ['a_u', 403], - ['g1_s1', 403], + ['g1_s1', 404], ['u1_s1', 200], - ['a1_s1', 200], - ['g1_s2', 403], + ['a1_s1', 404], + ['g1_s2', 404], ['u1_s2', 404], ['a1_s2', 404], ]) diff --git a/cookbook/tests/pytest/api/test_api_recipe_book.py b/cookbook/tests/pytest/api/test_api_recipe_book.py index cbf93fe8..3c5f4726 100644 --- a/cookbook/tests/pytest/api/test_api_recipe_book.py +++ b/cookbook/tests/pytest/api/test_api_recipe_book.py @@ -99,6 +99,7 @@ def test_add(arg, request, u1_s2): content_type='application/json' ) response = json.loads(r.content) + print(r.content) assert r.status_code == arg[1] if r.status_code == 201: assert response['name'] == 'test' diff --git a/cookbook/tests/pytest/api/test_api_userpreference.py b/cookbook/tests/pytest/api/test_api_userpreference.py new file mode 100644 index 00000000..3f819e93 --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_userpreference.py @@ -0,0 +1,118 @@ +import json + +from cookbook.models import UserPreference +from cookbook.tests.views.test_views import TestViews +from django.contrib import auth +from django.urls import reverse + +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import RecipeBook, RecipeBookEntry + +LIST_URL = 'api:userpreference-list' +DETAIL_URL = 'api:userpreference-detail' + + +def test_add(u1_s1, u2_s1): + r = u1_s1.post(reverse(LIST_URL)) + assert r.status_code == 400 + + with scopes_disabled(): + UserPreference.objects.filter(user=auth.get_user(u1_s1)).delete() + + r = u2_s1.post(reverse(LIST_URL), {'user': auth.get_user(u1_s1).id}, content_type='application/json') + assert r.status_code == 404 + + r = u1_s1.post(reverse(LIST_URL), {'user': auth.get_user(u1_s1).id}, content_type='application/json') + assert r.status_code == 200 + + +def test_preference_list(u1_s1, u2_s1, u1_s2): + # users can only see own preference in list + r = u1_s1.get(reverse(LIST_URL)) + assert r.status_code == 200 + response = json.loads(r.content) + assert len(response) == 1 + assert response[0]['user'] == auth.get_user(u1_s1).id + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 404], + ['u1_s1', 200], + ['a1_s1', 404], +]) +def test_preference_retrieve(arg, request, u1_s1): + c = request.getfixturevalue(arg[0]) + + r = c.get( + reverse(DETAIL_URL, args={auth.get_user(u1_s1).id}), + ) + assert r.status_code == arg[1] + + +def test_preference_update(u1_s1, u2_s1): + # can update users preference + r = u1_s1.put( + reverse( + DETAIL_URL, + args={auth.get_user(u1_s1).id} + ), + {'user': auth.get_user(u1_s1).id, 'theme': UserPreference.DARKLY}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == 200 + assert response['theme'] == UserPreference.DARKLY + + # cant set another users non existent pref + r = u1_s1.put( + reverse( + DETAIL_URL, + args={auth.get_user(u2_s1).id} + ), + {'user': auth.get_user(u1_s1).id, 'theme': UserPreference.DARKLY}, + content_type='application/json' + ) + assert r.status_code == 404 + + # cant set another users existent pref + with scopes_disabled(): + UserPreference.objects.filter(user=auth.get_user(u2_s1)).delete() + + r = u1_s1.put( + reverse( + DETAIL_URL, + args={auth.get_user(u2_s1).id} + ), + {'user': auth.get_user(u1_s1).id, 'theme': UserPreference.FLATLY}, + content_type='application/json' + ) + assert r.status_code == 404 + with scopes_disabled(): + assert not UserPreference.objects.filter(user=auth.get_user(u2_s1)).exists() + + +def test_preference_delete(u1_s1, u2_s1): + # cant delete other preference + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={auth.get_user(u2_s1).id} + ) + ) + assert r.status_code == 404 + + # can delete own preference + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={auth.get_user(u1_s1).id} + ) + ) + assert r.status_code == 204 diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 678fb672..d95ae482 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -16,8 +16,8 @@ from django.http import FileResponse, HttpResponse, JsonResponse from django.shortcuts import redirect from django.utils.translation import gettext as _ from icalendar import Calendar, Event -from rest_framework import decorators, viewsets -from rest_framework.exceptions import APIException, PermissionDenied +from rest_framework import decorators, viewsets, status +from rest_framework.exceptions import APIException, PermissionDenied, NotFound, MethodNotAllowed from rest_framework.parsers import MultiPartParser from rest_framework.response import Response from rest_framework.viewsets import ViewSetMixin @@ -97,7 +97,7 @@ class UserNameViewSet(viewsets.ReadOnlyModelViewSet): if filter_list is not None: queryset = queryset.filter(pk__in=json.loads(filter_list)) except ValueError: - raise APIException(_('Parameter filter_list incorrectly formatted')) + raise APIException('Parameter filter_list incorrectly formatted') return queryset @@ -107,11 +107,6 @@ class UserPreferenceViewSet(viewsets.ModelViewSet): serializer_class = UserPreferenceSerializer permission_classes = [CustomIsOwner, ] - def perform_create(self, serializer): - if UserPreference.objects.filter(user=self.request.user).exists(): - raise APIException(_('Preference for given user already exists')) - serializer.save(user=self.request.user) - def get_queryset(self): return self.queryset.filter(user=self.request.user) From ae81b10dbd2a35485108571400b914a9e58ca69a Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Tue, 16 Mar 2021 23:50:51 +0100 Subject: [PATCH 65/96] added supermarket api test --- cookbook/tests/api/test_api_supermarket.py | 0 .../tests/pytest/api/test_api_supermarket.py | 130 ++++++++++++++++++ 2 files changed, 130 insertions(+) delete mode 100644 cookbook/tests/api/test_api_supermarket.py create mode 100644 cookbook/tests/pytest/api/test_api_supermarket.py diff --git a/cookbook/tests/api/test_api_supermarket.py b/cookbook/tests/api/test_api_supermarket.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/pytest/api/test_api_supermarket.py b/cookbook/tests/pytest/api/test_api_supermarket.py new file mode 100644 index 00000000..318ad9e9 --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_supermarket.py @@ -0,0 +1,130 @@ +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import RecipeBook, Supermarket + +LIST_URL = 'api:supermarket-list' +DETAIL_URL = 'api:supermarket-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1): + return Supermarket.objects.get_or_create(name='test_1', space=space_1)[0] + + +@pytest.fixture +def obj_2(space_1, u1_s1): + return Supermarket.objects.get_or_create(name='test_2', space=space_1)[0] + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 1 + + +def test_list_filter(obj_1, obj_2, u1_s1): + r = u1_s1.get(reverse(LIST_URL)) + assert r.status_code == 200 + response = json.loads(r.content) + assert len(response) == 2 + assert response[0]['name'] == obj_1.name + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content) + assert len(response) == 1 + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query=chicken').content) + assert len(response) == 0 + + response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query={obj_1.name[4:]}').content) + assert len(response) == 1 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], + ['g1_s2', 403], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'name': 'new'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['name'] == 'new' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_add(arg, request, u1_s2): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'name': 'test'}, + content_type='application/json' + ) + response = json.loads(r.content) + print(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['name'] == 'test' + r = c.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 200 + r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert RecipeBook.objects.count() == 0 From a25109e16c7adc9f710eb5713016645b130bc02a Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 00:03:36 +0100 Subject: [PATCH 66/96] added sync api test --- cookbook/tests/api/test_api_sync.py | 68 ------------ cookbook/tests/pytest/api/test_api_sync.py | 115 +++++++++++++++++++++ 2 files changed, 115 insertions(+), 68 deletions(-) delete mode 100644 cookbook/tests/api/test_api_sync.py create mode 100644 cookbook/tests/pytest/api/test_api_sync.py diff --git a/cookbook/tests/api/test_api_sync.py b/cookbook/tests/api/test_api_sync.py deleted file mode 100644 index 26c84df1..00000000 --- a/cookbook/tests/api/test_api_sync.py +++ /dev/null @@ -1,68 +0,0 @@ -import json - -from cookbook.models import Storage, Sync -from cookbook.tests.views.test_views import TestViews -from django.contrib import auth -from django.urls import reverse - - -class TestApiSync(TestViews): - - def setUp(self): - super(TestApiSync, self).setUp() - self.storage = Storage.objects.create( - name='Test Storage', - username='test', - password='password', - token='token', - url='url', - created_by=auth.get_user(self.admin_client_1) - ) - - self.sync = Sync.objects.create( - storage=self.storage, - path='path' - ) - - def test_sync_list(self): - # verify view permissions are applied accordingly - self.batch_requests( - [ - (self.anonymous_client, 403), - (self.guest_client_1, 403), - (self.user_client_1, 403), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - reverse('api:sync-list') - ) - - # verify sync is returned - r = self.admin_client_1.get(reverse('api:sync-list')) - self.assertEqual(r.status_code, 200) - response = json.loads(r.content) - self.assertEqual(len(response), 1) - storage_response = response[0] - self.assertEqual(storage_response['path'], self.sync.path) - - def test_sync_update(self): - # can update sync as admin - r = self.admin_client_1.patch( - reverse( - 'api:sync-detail', - args={self.sync.id} - ), - {'path': 'new'}, - content_type='application/json' - ) - response = json.loads(r.content) - self.assertEqual(r.status_code, 200) - self.assertEqual(response['path'], 'new') - - def test_sync_delete(self): - # can delete sync as admin - r = self.admin_client_1.delete( - reverse('api:sync-detail', args={self.sync.id}) - ) - self.assertEqual(r.status_code, 204) - self.assertEqual(Sync.objects.count(), 0) diff --git a/cookbook/tests/pytest/api/test_api_sync.py b/cookbook/tests/pytest/api/test_api_sync.py new file mode 100644 index 00000000..90bd75ae --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_sync.py @@ -0,0 +1,115 @@ +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import RecipeBook, Storage, Sync + +LIST_URL = 'api:sync-list' +DETAIL_URL = 'api:sync-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1): + s = Storage.objects.create(name='Test Storage', username='test', password='password', token='token', url='url', created_by=auth.get_user(u1_s1), space=space_1, ) + return Sync.objects.create(storage=s, path='path', space=space_1, ) + + +@pytest.fixture +def obj_2(space_1, u1_s1): + s = Storage.objects.create(name='Test Storage', username='test', password='password', token='token', url='url', created_by=auth.get_user(u1_s1), space=space_1, ) + return Sync.objects.create(storage=s, path='path', space=space_1, ) + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 403], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, a1_s1, a1_s2, space_2): + assert len(json.loads(a1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(a1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(a1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(a1_s2.get(reverse(LIST_URL)).content)) == 1 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 403], + ['a1_s1', 200], + ['g1_s2', 403], + ['u1_s2', 403], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'path': 'new'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['path'] == 'new' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 403], + ['a1_s1', 201], +]) +def test_add(arg, request, a1_s2, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'storage': obj_1.storage.pk, 'path': 'test'}, + content_type='application/json' + ) + response = json.loads(r.content) + print(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['path'] == 'test' + r = c.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 200 + r = a1_s2.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 + + +def test_delete(a1_s1, a1_s2, obj_1): + r = a1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = a1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert RecipeBook.objects.count() == 0 From c2addc11217e844d7ed14a5b877a64a7b5b71113 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 00:14:54 +0100 Subject: [PATCH 67/96] storage api test --- cookbook/serializer.py | 7 + cookbook/tests/api/test_api_storage.py | 82 ------------ cookbook/tests/pytest/api/test_api_storage.py | 122 ++++++++++++++++++ 3 files changed, 129 insertions(+), 82 deletions(-) delete mode 100644 cookbook/tests/api/test_api_storage.py create mode 100644 cookbook/tests/pytest/api/test_api_storage.py diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 1b8bcc38..985aa03b 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -87,6 +87,11 @@ class UserPreferenceSerializer(serializers.ModelSerializer): class StorageSerializer(SpacedModelSerializer): + + def create(self, validated_data): + validated_data['created_by'] = self.context['request'].user + return super().create(validated_data) + class Meta: model = Storage fields = ( @@ -94,6 +99,8 @@ class StorageSerializer(SpacedModelSerializer): 'token', 'created_by' ) + read_only_fields = ('created_by',) + extra_kwargs = { 'password': {'write_only': True}, 'token': {'write_only': True}, diff --git a/cookbook/tests/api/test_api_storage.py b/cookbook/tests/api/test_api_storage.py deleted file mode 100644 index 64f57ff8..00000000 --- a/cookbook/tests/api/test_api_storage.py +++ /dev/null @@ -1,82 +0,0 @@ -import json - -from cookbook.models import Storage, Sync -from cookbook.tests.views.test_views import TestViews -from django.contrib import auth -from django.db.models import ProtectedError -from django.urls import reverse - - -class TestApiStorage(TestViews): - - def setUp(self): - super(TestApiStorage, self).setUp() - self.storage = Storage.objects.create( - name='Test Storage', - username='test', - password='password', - token='token', - url='url', - created_by=auth.get_user(self.admin_client_1) - ) - - def test_storage_list(self): - # verify view permissions are applied accordingly - self.batch_requests( - [ - (self.anonymous_client, 403), - (self.guest_client_1, 403), - (self.user_client_1, 403), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - reverse('api:storage-list') - ) - - # verify storage is returned - r = self.admin_client_1.get(reverse('api:storage-list')) - self.assertEqual(r.status_code, 200) - response = json.loads(r.content) - self.assertEqual(len(response), 1) - storage_response = response[0] - self.assertEqual(storage_response['name'], self.storage.name) - self.assertFalse('password' in storage_response) - self.assertFalse('token' in storage_response) - - def test_storage_update(self): - # can update storage as admin - r = self.admin_client_1.patch( - reverse( - 'api:storage-detail', - args={self.storage.id} - ), - {'name': 'new', 'password': 'new_password'}, - content_type='application/json' - ) - response = json.loads(r.content) - self.assertEqual(r.status_code, 200) - self.assertEqual(response['name'], 'new') - - # verify password was updated (write only field) - self.storage.refresh_from_db() - self.assertEqual(self.storage.password, 'new_password') - - def test_storage_delete(self): - # can delete storage as admin - r = self.admin_client_1.delete( - reverse('api:storage-detail', args={self.storage.id}) - ) - self.assertEqual(r.status_code, 204) - self.assertEqual(Storage.objects.count(), 0) - - self.storage = Storage.objects.create( - created_by=auth.get_user(self.admin_client_1), name='test protect' - ) - Sync.objects.create(storage=self.storage, ) - - # test if deleting a storage with existing - # sync fails (as sync protects storage) - with self.assertRaises(ProtectedError): - self.admin_client_1.delete( - reverse('api:storage-detail', args={self.storage.id}) - ) diff --git a/cookbook/tests/pytest/api/test_api_storage.py b/cookbook/tests/pytest/api/test_api_storage.py new file mode 100644 index 00000000..0fac895a --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_storage.py @@ -0,0 +1,122 @@ +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import RecipeBook, Storage, Sync + +LIST_URL = 'api:storage-list' +DETAIL_URL = 'api:storage-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1): + return Storage.objects.create(name='Test Storage 1', username='test', password='password', token='token', url='url', created_by=auth.get_user(u1_s1), space=space_1, ) + + +@pytest.fixture +def obj_2(space_1, u1_s1): + return Storage.objects.create(name='Test Storage 2', username='test', password='password', token='token', url='url', created_by=auth.get_user(u1_s1), space=space_1, ) + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 403], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + r = c.get(reverse(LIST_URL)) + assert r.status_code == arg[1] + if r.status_code == 200: + response = json.loads(r.content) + assert 'password' not in response + assert 'token' not in response + + +def test_list_space(obj_1, obj_2, a1_s1, a1_s2, space_2): + assert len(json.loads(a1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(a1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(a1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(a1_s2.get(reverse(LIST_URL)).content)) == 1 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 403], + ['a1_s1', 200], + ['g1_s2', 403], + ['u1_s2', 403], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + test_password = '1234' + + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'name': 'new', 'password': test_password}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['name'] == 'new' + obj_1.refresh_from_db() + assert obj_1.password == test_password + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 403], + ['a1_s1', 201], +]) +def test_add(arg, request, a1_s2, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'name': 'test', 'method': Storage.DROPBOX}, + content_type='application/json' + ) + response = json.loads(r.content) + print(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['name'] == 'test' + r = c.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 200 + r = a1_s2.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 + + +def test_delete(a1_s1, a1_s2, obj_1): + r = a1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = a1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert RecipeBook.objects.count() == 0 From b48708652fa6934b44238163c5d97687c1d7f519 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 00:27:53 +0100 Subject: [PATCH 68/96] delete model check fixes + sync log --- .../migrations/0112_remove_synclog_space.py | 17 +++ cookbook/models.py | 3 +- cookbook/provider/dropbox.py | 3 +- cookbook/provider/local.py | 1 - cookbook/provider/nextcloud.py | 1 - cookbook/tests/api/test_api_sync_log.py | 70 ------------ .../tests/pytest/api/test_api_meal_type.py | 2 +- cookbook/tests/pytest/api/test_api_storage.py | 2 +- .../tests/pytest/api/test_api_supermarket.py | 2 +- cookbook/tests/pytest/api/test_api_sync.py | 2 +- .../tests/pytest/api/test_api_sync_log.py | 105 ++++++++++++++++++ cookbook/views/api.py | 2 +- 12 files changed, 129 insertions(+), 81 deletions(-) create mode 100644 cookbook/migrations/0112_remove_synclog_space.py delete mode 100644 cookbook/tests/api/test_api_sync_log.py create mode 100644 cookbook/tests/pytest/api/test_api_sync_log.py diff --git a/cookbook/migrations/0112_remove_synclog_space.py b/cookbook/migrations/0112_remove_synclog_space.py new file mode 100644 index 00000000..37bf9759 --- /dev/null +++ b/cookbook/migrations/0112_remove_synclog_space.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1.7 on 2021-03-16 23:21 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0111_space_created_by'), + ] + + operations = [ + migrations.RemoveField( + model_name='synclog', + name='space', + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index cd335f7c..acfdb7ab 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -220,8 +220,7 @@ class SyncLog(models.Model, PermissionModelMixin): msg = models.TextField(default="") created_at = models.DateTimeField(auto_now_add=True) - space = models.ForeignKey(Space, on_delete=models.CASCADE) - objects = ScopedManager(space='space') + objects = ScopedManager(space='sync__space') def __str__(self): return f"{self.created_at}:{self.sync} - {self.status}" diff --git a/cookbook/provider/dropbox.py b/cookbook/provider/dropbox.py index af3d410e..ca6994b9 100644 --- a/cookbook/provider/dropbox.py +++ b/cookbook/provider/dropbox.py @@ -27,7 +27,7 @@ class Dropbox(Provider): try: recipes = r.json() except ValueError: - log_entry = SyncLog(status='ERROR', msg=str(r), sync=monitor, space=monitor.space) + log_entry = SyncLog(status='ERROR', msg=str(r), sync=monitor) log_entry.save() return r @@ -51,7 +51,6 @@ class Dropbox(Provider): status='SUCCESS', msg='Imported ' + str(import_count) + ' recipes', sync=monitor, - space=monitor.space, ) log_entry.save() diff --git a/cookbook/provider/local.py b/cookbook/provider/local.py index 1298e3e4..d24c4eb1 100644 --- a/cookbook/provider/local.py +++ b/cookbook/provider/local.py @@ -33,7 +33,6 @@ class Local(Provider): status='SUCCESS', msg='Imported ' + str(import_count) + ' recipes', sync=monitor, - space=monitor.space, ) log_entry.save() diff --git a/cookbook/provider/nextcloud.py b/cookbook/provider/nextcloud.py index f11109ed..d67c0244 100644 --- a/cookbook/provider/nextcloud.py +++ b/cookbook/provider/nextcloud.py @@ -49,7 +49,6 @@ class Nextcloud(Provider): status='SUCCESS', msg='Imported ' + str(import_count) + ' recipes', sync=monitor, - space=monitor.space ) log_entry.save() diff --git a/cookbook/tests/api/test_api_sync_log.py b/cookbook/tests/api/test_api_sync_log.py deleted file mode 100644 index 0efaaabd..00000000 --- a/cookbook/tests/api/test_api_sync_log.py +++ /dev/null @@ -1,70 +0,0 @@ -import json - -from cookbook.models import Storage, Sync, SyncLog -from cookbook.tests.views.test_views import TestViews -from django.contrib import auth -from django.urls import reverse - - -class TestApiSyncLog(TestViews): - - def setUp(self): - super(TestApiSyncLog, self).setUp() - self.storage = Storage.objects.create( - name='Test Storage', - username='test', - password='password', - token='token', - url='url', - created_by=auth.get_user(self.admin_client_1) - ) - - self.sync = Sync.objects.create( - storage=self.storage, - path='path' - ) - - self.sync_log = SyncLog.objects.create( - sync=self.sync, status='success' - ) - - def test_sync_log_list(self): - # verify view permissions are applied accordingly - self.batch_requests( - [ - (self.anonymous_client, 403), - (self.guest_client_1, 403), - (self.user_client_1, 403), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - reverse('api:synclog-list') - ) - - # verify log entry is returned - r = self.admin_client_1.get(reverse('api:synclog-list')) - self.assertEqual(r.status_code, 200) - response = json.loads(r.content) - self.assertEqual(len(response), 1) - self.assertEqual(response[0]['status'], self.sync_log.status) - - def test_sync_log_update(self): - # read only view - r = self.admin_client_1.patch( - reverse( - 'api:synclog-detail', - args={self.sync.id} - ), - {'path': 'new'}, - content_type='application/json' - ) - self.assertEqual(r.status_code, 405) - - def test_sync_log_delete(self): - # read only view - r = self.admin_client_1.delete( - reverse( - 'api:synclog-detail', - args={self.sync.id}) - ) - self.assertEqual(r.status_code, 405) diff --git a/cookbook/tests/pytest/api/test_api_meal_type.py b/cookbook/tests/pytest/api/test_api_meal_type.py index 17e0a7ea..de3c73da 100644 --- a/cookbook/tests/pytest/api/test_api_meal_type.py +++ b/cookbook/tests/pytest/api/test_api_meal_type.py @@ -129,4 +129,4 @@ def test_delete(u1_s1, u1_s2, obj_1): assert r.status_code == 204 with scopes_disabled(): - assert Food.objects.count() == 0 + assert MealType.objects.count() == 0 diff --git a/cookbook/tests/pytest/api/test_api_storage.py b/cookbook/tests/pytest/api/test_api_storage.py index 0fac895a..b1302a58 100644 --- a/cookbook/tests/pytest/api/test_api_storage.py +++ b/cookbook/tests/pytest/api/test_api_storage.py @@ -119,4 +119,4 @@ def test_delete(a1_s1, a1_s2, obj_1): assert r.status_code == 204 with scopes_disabled(): - assert RecipeBook.objects.count() == 0 + assert Storage.objects.count() == 0 diff --git a/cookbook/tests/pytest/api/test_api_supermarket.py b/cookbook/tests/pytest/api/test_api_supermarket.py index 318ad9e9..76c7cf41 100644 --- a/cookbook/tests/pytest/api/test_api_supermarket.py +++ b/cookbook/tests/pytest/api/test_api_supermarket.py @@ -127,4 +127,4 @@ def test_delete(u1_s1, u1_s2, obj_1): assert r.status_code == 204 with scopes_disabled(): - assert RecipeBook.objects.count() == 0 + assert Supermarket.objects.count() == 0 diff --git a/cookbook/tests/pytest/api/test_api_sync.py b/cookbook/tests/pytest/api/test_api_sync.py index 90bd75ae..7a7d9d46 100644 --- a/cookbook/tests/pytest/api/test_api_sync.py +++ b/cookbook/tests/pytest/api/test_api_sync.py @@ -112,4 +112,4 @@ def test_delete(a1_s1, a1_s2, obj_1): assert r.status_code == 204 with scopes_disabled(): - assert RecipeBook.objects.count() == 0 + assert Sync.objects.count() == 0 diff --git a/cookbook/tests/pytest/api/test_api_sync_log.py b/cookbook/tests/pytest/api/test_api_sync_log.py new file mode 100644 index 00000000..579699dd --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_sync_log.py @@ -0,0 +1,105 @@ +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import RecipeBook, Storage, Sync, SyncLog + +LIST_URL = 'api:synclog-list' +DETAIL_URL = 'api:synclog-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1): + s = Storage.objects.create(name='Test Storage 1', username='test', password='password', token='token', url='url', created_by=auth.get_user(u1_s1), space=space_1, ) + sy = Sync.objects.create(storage=s, path='path', space=space_1, ) + return SyncLog.objects.create(sync=sy, status=1) + + +@pytest.fixture +def obj_2(space_1, u1_s1): + s = Storage.objects.create(name='Test Storage 2', username='test', password='password', token='token', url='url', created_by=auth.get_user(u1_s1), space=space_1, ) + sy = Sync.objects.create(storage=s, path='path', space=space_1, ) + return SyncLog.objects.create(sync=sy, status=1) + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 403], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, a1_s1, a1_s2, space_2): + assert len(json.loads(a1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(a1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.sync.space = space_2 + obj_1.sync.save() + + assert len(json.loads(a1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(a1_s2.get(reverse(LIST_URL)).content)) == 1 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 403], + ['a1_s1', 405], + ['g1_s2', 403], + ['u1_s2', 403], + ['a1_s2', 405], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'msg': 'new'}, + content_type='application/json' + ) + assert r.status_code == arg[1] + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 403], + ['a1_s1', 405], +]) +def test_add(arg, request, a1_s2, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'msg': 'test'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + + +def test_delete(a1_s1, a1_s2, obj_1): + r = a1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 405 + + r = a1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 405 diff --git a/cookbook/views/api.py b/cookbook/views/api.py index d95ae482..301be9ec 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -136,7 +136,7 @@ class SyncLogViewSet(viewsets.ReadOnlyModelViewSet): permission_classes = [CustomIsAdmin, ] def get_queryset(self): - return self.queryset.filter(space=self.request.user.userpreference.space) + return self.queryset.filter(sync__space=self.request.user.userpreference.space) class SupermarketViewSet(viewsets.ModelViewSet, StandardFilterMixin): From 641feede74c025034ac9e1a39d9651b06bc64018 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 19:55:34 +0100 Subject: [PATCH 69/96] space nested serializers --- cookbook/models.py | 40 ++++-- cookbook/serializer.py | 16 ++- cookbook/tests/api/test_api_shopping_list.py | 48 ------- .../pytest/api/test_api_shopping_list.py | 120 ++++++++++++++++++ cookbook/views/api.py | 40 +++--- 5 files changed, 186 insertions(+), 78 deletions(-) delete mode 100644 cookbook/tests/api/test_api_shopping_list.py create mode 100644 cookbook/tests/pytest/api/test_api_shopping_list.py diff --git a/cookbook/models.py b/cookbook/models.py index acfdb7ab..e0935a39 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -30,6 +30,14 @@ def get_model_name(model): class PermissionModelMixin: + + @staticmethod + def get_space_key(): + return ('space',) + + def get_space_kwarg(self): + return '__'.join(self.get_space_key()) + def get_owner(self): if getattr(self, 'created_by', None): return self.created_by @@ -38,8 +46,9 @@ class PermissionModelMixin: return None def get_space(self): - if getattr(self, 'space', None): - return self.space + p = '.'.join(self.get_space_key()) + if getattr(self, p, None): + return getattr(self, p) raise NotImplementedError('get space for method not implemented and standard fields not available') @@ -207,8 +216,9 @@ class SupermarketCategoryRelation(models.Model, PermissionModelMixin): objects = ScopedManager(space='supermarket__space') - def get_space(self): - return self.supermarket.space + @staticmethod + def get_space_key(): + return 'supermarket', 'space' class Meta: ordering = ('order',) @@ -288,6 +298,10 @@ class Ingredient(models.Model, PermissionModelMixin): objects = ScopedManager(space='step__recipe__space') + @staticmethod + def get_space_key(): + return 'step', 'recipe', 'space' + def get_space(self): return self.step_set.first().recipe_set.first().space @@ -316,6 +330,10 @@ class Step(models.Model, PermissionModelMixin): objects = ScopedManager(space='recipe__space') + @staticmethod + def get_space_key(): + return 'recipe', 'space' + def get_space(self): return self.recipe_set.first().space @@ -340,6 +358,10 @@ class NutritionInformation(models.Model, PermissionModelMixin): objects = ScopedManager(space='recipe__space') + @staticmethod + def get_space_key(): + return 'recipe', 'space' + def get_space(self): return self.recipe_set.first().space @@ -388,8 +410,9 @@ class Comment(models.Model, PermissionModelMixin): objects = ScopedManager(space='recipe__space') - def get_space(self): - return self.recipe.space + @staticmethod + def get_space_key(): + return 'recipe', 'space' def __str__(self): return self.text @@ -429,8 +452,9 @@ class RecipeBookEntry(models.Model, PermissionModelMixin): objects = ScopedManager(space='book__space') - def get_space(self): - return self.book.space + @staticmethod + def get_space_key(): + return 'book', 'space' def __str__(self): return self.recipe.name diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 985aa03b..116329b0 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -41,6 +41,16 @@ class CustomDecimalField(serializers.Field): raise ValidationError('A valid number is required') +class SpaceFilterSerializer(serializers.ListSerializer): + + def to_representation(self, data): + if self.child.Meta.model == User: + data = data.filter(userpreference__space=self.context['request'].space) + else: + data = data.filter(**{'__'.join(data.model.get_space_key()): self.context['request'].space}) + return super().to_representation(data) + + class SpacedModelSerializer(serializers.ModelSerializer): def create(self, validated_data): validated_data['space'] = self.context['request'].space @@ -54,6 +64,7 @@ class MealTypeSerializer(SpacedModelSerializer): return super().create(validated_data) class Meta: + list_serializer_class = SpaceFilterSerializer model = MealType fields = ('id', 'name', 'order', 'created_by') read_only_fields = ('created_by',) @@ -66,6 +77,7 @@ class UserNameSerializer(WritableNestedModelSerializer): return obj.get_user_name() class Meta: + list_serializer_class = SpaceFilterSerializer model = User fields = ('id', 'username') @@ -129,6 +141,7 @@ class KeywordLabelSerializer(serializers.ModelSerializer): return str(obj) class Meta: + list_serializer_class = SpaceFilterSerializer model = Keyword fields = ( 'id', 'label', @@ -383,6 +396,7 @@ class ShoppingListSerializer(WritableNestedModelSerializer): def create(self, validated_data): validated_data['space'] = self.context['request'].space + validated_data['created_by'] = self.context['request'].user return super().create(validated_data) class Meta: @@ -391,7 +405,7 @@ class ShoppingListSerializer(WritableNestedModelSerializer): 'id', 'uuid', 'note', 'recipes', 'entries', 'shared', 'finished', 'supermarket', 'created_by', 'created_at' ) - read_only_fields = ('id',) + read_only_fields = ('id', 'created_by',) class ShoppingListAutoSyncSerializer(WritableNestedModelSerializer): diff --git a/cookbook/tests/api/test_api_shopping_list.py b/cookbook/tests/api/test_api_shopping_list.py deleted file mode 100644 index e25a16a5..00000000 --- a/cookbook/tests/api/test_api_shopping_list.py +++ /dev/null @@ -1,48 +0,0 @@ -from cookbook.models import ShoppingList -from cookbook.tests.views.test_views import TestViews -from django.contrib import auth -from django.urls import reverse - - -class TestApiShopping(TestViews): - - def setUp(self): - super(TestApiShopping, self).setUp() - self.list_1 = ShoppingList.objects.create( - created_by=auth.get_user(self.user_client_1) - ) - self.list_2 = ShoppingList.objects.create( - created_by=auth.get_user(self.user_client_2) - ) - - def test_shopping_view_permissions(self): - self.batch_requests( - [ - (self.anonymous_client, 403), - (self.guest_client_1, 404), - (self.user_client_1, 200), - (self.user_client_2, 404), - (self.admin_client_1, 404), - (self.superuser_client, 200) - ], - reverse( - 'api:shoppinglist-detail', args={self.list_1.id} - ) - ) - - self.list_1.shared.add(auth.get_user(self.user_client_2)) - - self.batch_requests( - [ - (self.anonymous_client, 403), - (self.guest_client_1, 404), - (self.user_client_1, 200), - (self.user_client_2, 200), - (self.admin_client_1, 404), - (self.superuser_client, 200) - ], - reverse( - 'api:shoppinglist-detail', args={self.list_1.id}) - ) - - # TODO add tests for editing diff --git a/cookbook/tests/pytest/api/test_api_shopping_list.py b/cookbook/tests/pytest/api/test_api_shopping_list.py new file mode 100644 index 00000000..25ba175a --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_shopping_list.py @@ -0,0 +1,120 @@ +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import RecipeBook, Storage, Sync, SyncLog, ShoppingList + +LIST_URL = 'api:shoppinglist-list' +DETAIL_URL = 'api:shoppinglist-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1): + return ShoppingList.objects.create(created_by=auth.get_user(u1_s1), space=space_1, ) + + +@pytest.fixture +def obj_2(space_1, u1_s1): + return ShoppingList.objects.create(created_by=auth.get_user(u1_s1), space=space_1, ) + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + +def test_share(obj_1, u1_s1, u2_s1, u1_s2): + assert u1_s1.get(reverse(DETAIL_URL, args={obj_1.id})).status_code == 200 + assert u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).status_code == 404 + assert u1_s2.get(reverse(DETAIL_URL, args={obj_1.id})).status_code == 404 + + obj_1.shared.add(auth.get_user(u2_s1)) + obj_1.shared.add(auth.get_user(u1_s2)) + + assert u1_s1.get(reverse(DETAIL_URL, args={obj_1.id})).status_code == 200 + assert u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).status_code == 200 + assert u1_s2.get(reverse(DETAIL_URL, args={obj_1.id})).status_code == 404 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 404], + ['u1_s1', 200], + ['a1_s1', 404], + ['g1_s2', 404], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'note': 'new'}, + content_type='application/json' + ) + assert r.status_code == arg[1] + if r.status_code == 200: + response = json.loads(r.content) + assert response['note'] == 'new' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 201], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_add(arg, request): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'note': 'test', 'recipes': [], 'shared': [], 'entries': [], 'supermarket': None}, + content_type='application/json' + ) + response = json.loads(r.content) + print(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['note'] == 'test' + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 301be9ec..173b4a95 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -91,7 +91,7 @@ class UserNameViewSet(viewsets.ReadOnlyModelViewSet): http_method_names = ['get'] def get_queryset(self): - queryset = self.queryset.filter(userpreference__space=self.request.user.userpreference.space) + queryset = self.queryset.filter(userpreference__space=self.request.space) try: filter_list = self.request.query_params.get('filter_list', None) if filter_list is not None: @@ -118,7 +118,7 @@ class StorageViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsAdmin, ] def get_queryset(self): - return self.queryset.filter(space=self.request.user.userpreference.space) + return self.queryset.filter(space=self.request.space) class SyncViewSet(viewsets.ModelViewSet): @@ -127,7 +127,7 @@ class SyncViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsAdmin, ] def get_queryset(self): - return self.queryset.filter(space=self.request.user.userpreference.space) + return self.queryset.filter(space=self.request.space) class SyncLogViewSet(viewsets.ReadOnlyModelViewSet): @@ -136,7 +136,7 @@ class SyncLogViewSet(viewsets.ReadOnlyModelViewSet): permission_classes = [CustomIsAdmin, ] def get_queryset(self): - return self.queryset.filter(sync__space=self.request.user.userpreference.space) + return self.queryset.filter(sync__space=self.request.space) class SupermarketViewSet(viewsets.ModelViewSet, StandardFilterMixin): @@ -145,7 +145,7 @@ class SupermarketViewSet(viewsets.ModelViewSet, StandardFilterMixin): permission_classes = [CustomIsUser] def get_queryset(self): - self.queryset = self.queryset.filter(space=self.request.user.userpreference.space) + self.queryset = self.queryset.filter(space=self.request.space) return super().get_queryset() @@ -163,7 +163,7 @@ class KeywordViewSet(viewsets.ModelViewSet, StandardFilterMixin): permission_classes = [CustomIsUser] def get_queryset(self): - self.queryset = self.queryset.filter(space=self.request.user.userpreference.space) + self.queryset = self.queryset.filter(space=self.request.space) return super().get_queryset() @@ -173,7 +173,7 @@ class UnitViewSet(viewsets.ModelViewSet, StandardFilterMixin): permission_classes = [CustomIsUser] def get_queryset(self): - self.queryset = self.queryset.filter(space=self.request.user.userpreference.space) + self.queryset = self.queryset.filter(space=self.request.space) return super().get_queryset() @@ -183,7 +183,7 @@ class FoodViewSet(viewsets.ModelViewSet, StandardFilterMixin): permission_classes = [CustomIsUser] def get_queryset(self): - self.queryset = self.queryset.filter(space=self.request.user.userpreference.space) + self.queryset = self.queryset.filter(space=self.request.space) return super().get_queryset() @@ -193,7 +193,7 @@ class RecipeBookViewSet(viewsets.ModelViewSet, StandardFilterMixin): permission_classes = [CustomIsOwner] def get_queryset(self): - self.queryset = self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space) + self.queryset = self.queryset.filter(created_by=self.request.user).filter(space=self.request.space) return super().get_queryset() @@ -203,7 +203,7 @@ class RecipeBookEntryViewSet(viewsets.ModelViewSet, viewsets.GenericViewSet): permission_classes = [CustomIsOwner] def get_queryset(self): - return self.queryset.filter(book__created_by=self.request.user).filter(book__space=self.request.user.userpreference.space) + return self.queryset.filter(book__created_by=self.request.user).filter(book__space=self.request.space) class MealPlanViewSet(viewsets.ModelViewSet): @@ -223,7 +223,7 @@ class MealPlanViewSet(viewsets.ModelViewSet): queryset = self.queryset.filter( Q(created_by=self.request.user) | Q(shared=self.request.user) - ).filter(space=self.request.user.userpreference.space).distinct().all() + ).filter(space=self.request.space).distinct().all() from_date = self.request.query_params.get('from_date', None) if from_date is not None: @@ -245,7 +245,7 @@ class MealTypeViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsOwner] def get_queryset(self): - queryset = self.queryset.order_by('order', 'id').filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all() + queryset = self.queryset.order_by('order', 'id').filter(created_by=self.request.user).filter(space=self.request.space).all() return queryset @@ -255,7 +255,7 @@ class IngredientViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsUser] def get_queryset(self): - return self.queryset.filter(step__recipe__space=self.request.user.userpreference.space) + return self.queryset.filter(step__recipe__space=self.request.space) class StepViewSet(viewsets.ModelViewSet): @@ -264,7 +264,7 @@ class StepViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsUser] def get_queryset(self): - return self.queryset.filter(recipe__space=self.request.user.userpreference.space) + return self.queryset.filter(recipe__space=self.request.space) class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin): @@ -340,7 +340,7 @@ class ShoppingListRecipeViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsOwner, ] def get_queryset(self): - return self.queryset.filter(shoppinglist__created_by=self.request.user).filter(space=self.request.user.userpreference.space).all() + return self.queryset.filter(shoppinglist__created_by=self.request.user).filter(space=self.request.space).all() class ShoppingListEntryViewSet(viewsets.ModelViewSet): @@ -349,7 +349,7 @@ class ShoppingListEntryViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsOwner, ] def get_queryset(self): - return self.queryset.filter(shoppinglist__created_by=self.request.user).filter(space=self.request.user.userpreference.space).all() + return self.queryset.filter(shoppinglist__created_by=self.request.user).filter(space=self.request.space).all() class ShoppingListViewSet(viewsets.ModelViewSet): @@ -358,9 +358,7 @@ class ShoppingListViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsOwner | CustomIsShared] def get_queryset(self): - return self.queryset.filter( - Q(created_by=self.request.user) | Q(shared=self.request.user) - ).filter(space=self.request.user.userpreference.space).all() + return self.queryset.filter(Q(created_by=self.request.user) | Q(shared=self.request.user)).filter(space=self.request.space).distinct() def get_serializer_class(self): autosync = self.request.query_params.get('autosync', None) @@ -375,7 +373,7 @@ class ViewLogViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsOwner] def get_queryset(self): - self.queryset = self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all() + self.queryset = self.queryset.filter(created_by=self.request.user).filter(space=self.request.space).all() if self.request.method == 'GET': return self.queryset[:5] else: @@ -388,7 +386,7 @@ class CookLogViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsOwner] def get_queryset(self): - self.queryset = self.queryset.filter(created_by=self.request.user).filter(space=self.request.user.userpreference.space).all() + self.queryset = self.queryset.filter(created_by=self.request.user).filter(space=self.request.space).all() if self.request.method == 'GET': return self.queryset[:5] else: From e968a57c06a1b6e9af3836577643f9fcb5e9683d Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 20:42:17 +0100 Subject: [PATCH 70/96] shopping list api tests and refactors --- .../migrations/0113_auto_20210317_2017.py | 21 ++++ cookbook/models.py | 20 ++- cookbook/serializer.py | 4 +- .../tests/api/test_api_shopping_list_entry.py | 0 .../api/test_api_shopping_list_recipe.py | 0 .../api/test_api_shopping_list_entry.py | 116 ++++++++++++++++++ .../api/test_api_shopping_list_recipe.py | 116 ++++++++++++++++++ cookbook/views/api.py | 4 +- 8 files changed, 273 insertions(+), 8 deletions(-) create mode 100644 cookbook/migrations/0113_auto_20210317_2017.py delete mode 100644 cookbook/tests/api/test_api_shopping_list_entry.py delete mode 100644 cookbook/tests/api/test_api_shopping_list_recipe.py create mode 100644 cookbook/tests/pytest/api/test_api_shopping_list_entry.py create mode 100644 cookbook/tests/pytest/api/test_api_shopping_list_recipe.py diff --git a/cookbook/migrations/0113_auto_20210317_2017.py b/cookbook/migrations/0113_auto_20210317_2017.py new file mode 100644 index 00000000..29dd1596 --- /dev/null +++ b/cookbook/migrations/0113_auto_20210317_2017.py @@ -0,0 +1,21 @@ +# Generated by Django 3.1.7 on 2021-03-17 19:17 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0112_remove_synclog_space'), + ] + + operations = [ + migrations.RemoveField( + model_name='shoppinglistentry', + name='space', + ), + migrations.RemoveField( + model_name='shoppinglistrecipe', + name='space', + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index e0935a39..c99cb691 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -510,8 +510,14 @@ class ShoppingListRecipe(models.Model, PermissionModelMixin): recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, null=True, blank=True) servings = models.DecimalField(default=1, max_digits=8, decimal_places=4) - space = models.ForeignKey(Space, on_delete=models.CASCADE) - objects = ScopedManager(space='space') + objects = ScopedManager(space='shoppinglist__space') + + @staticmethod + def get_space_key(): + return 'shoppinglist', 'space' + + def get_space(self): + return self.shoppinglist_set.first().space def __str__(self): return f'Shopping list recipe {self.id} - {self.recipe}' @@ -531,8 +537,14 @@ class ShoppingListEntry(models.Model, PermissionModelMixin): order = models.IntegerField(default=0) checked = models.BooleanField(default=False) - space = models.ForeignKey(Space, on_delete=models.CASCADE) - objects = ScopedManager(space='space') + objects = ScopedManager(space='shoppinglist__space') + + @staticmethod + def get_space_key(): + return 'shoppinglist', 'space' + + def get_space(self): + return self.shoppinglist_set.first().space def __str__(self): return f'Shopping list entry {self.id}' diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 116329b0..57ddb143 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -360,7 +360,7 @@ class MealPlanSerializer(SpacedModelSerializer): read_only_fields = ('created_by',) -class ShoppingListRecipeSerializer(SpacedModelSerializer): +class ShoppingListRecipeSerializer(serializers.ModelSerializer): recipe_name = serializers.ReadOnlyField(source='recipe.name') servings = CustomDecimalField() @@ -370,7 +370,7 @@ class ShoppingListRecipeSerializer(SpacedModelSerializer): read_only_fields = ('id',) -class ShoppingListEntrySerializer(SpacedModelSerializer): +class ShoppingListEntrySerializer(WritableNestedModelSerializer): food = FoodSerializer(allow_null=True) unit = UnitSerializer(allow_null=True, required=False) amount = CustomDecimalField() diff --git a/cookbook/tests/api/test_api_shopping_list_entry.py b/cookbook/tests/api/test_api_shopping_list_entry.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/api/test_api_shopping_list_recipe.py b/cookbook/tests/api/test_api_shopping_list_recipe.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/pytest/api/test_api_shopping_list_entry.py b/cookbook/tests/pytest/api/test_api_shopping_list_entry.py new file mode 100644 index 00000000..323e2004 --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_shopping_list_entry.py @@ -0,0 +1,116 @@ +import json + +import pytest +from django.contrib import auth +from django.forms import model_to_dict +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import RecipeBook, Storage, Sync, SyncLog, ShoppingList, ShoppingListEntry, Food + +LIST_URL = 'api:shoppinglistentry-list' +DETAIL_URL = 'api:shoppinglistentry-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1): + e = ShoppingListEntry.objects.create(food=Food.objects.create(name='test 1', space=space_1)) + s = ShoppingList.objects.create(created_by=auth.get_user(u1_s1), space=space_1, ) + s.entries.add(e) + return e + + +@pytest.fixture +def obj_2(space_1, u1_s1): + e = ShoppingListEntry.objects.create(food=Food.objects.create(name='test 2', space=space_1)) + s = ShoppingList.objects.create(created_by=auth.get_user(u1_s1), space=space_1, ) + s.entries.add(e) + return e + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + with scopes_disabled(): + s = ShoppingList.objects.first() + s.space = space_2 + s.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 404], + ['u1_s1', 200], + ['a1_s1', 404], + ['g1_s2', 404], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'amount': 2}, + content_type='application/json' + ) + assert r.status_code == arg[1] + if r.status_code == 200: + response = json.loads(r.content) + assert response['amount'] == 2 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 201], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_add(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'food': model_to_dict(obj_1.food), 'amount': 1}, + content_type='application/json' + ) + response = json.loads(r.content) + print(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['food']['id'] == obj_1.food.pk + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 diff --git a/cookbook/tests/pytest/api/test_api_shopping_list_recipe.py b/cookbook/tests/pytest/api/test_api_shopping_list_recipe.py new file mode 100644 index 00000000..f52de5d0 --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_shopping_list_recipe.py @@ -0,0 +1,116 @@ +import json + +import pytest +from django.contrib import auth +from django.forms import model_to_dict +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import RecipeBook, Storage, Sync, SyncLog, ShoppingList, ShoppingListEntry, Food, ShoppingListRecipe + +LIST_URL = 'api:shoppinglistrecipe-list' +DETAIL_URL = 'api:shoppinglistrecipe-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1, recipe_1_s1): + r = ShoppingListRecipe.objects.create(recipe=recipe_1_s1, servings=1) + s = ShoppingList.objects.create(created_by=auth.get_user(u1_s1), space=space_1, ) + s.recipes.add(r) + return r + + +@pytest.fixture +def obj_2(space_1, u1_s1,recipe_1_s1): + r = ShoppingListRecipe.objects.create(recipe=recipe_1_s1, servings=1) + s = ShoppingList.objects.create(created_by=auth.get_user(u1_s1), space=space_1, ) + s.recipes.add(r) + return r + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + with scopes_disabled(): + s = ShoppingList.objects.first() + s.space = space_2 + s.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 404], + ['u1_s1', 200], + ['a1_s1', 404], + ['g1_s2', 404], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'servings': 2}, + content_type='application/json' + ) + assert r.status_code == arg[1] + if r.status_code == 200: + response = json.loads(r.content) + assert response['servings'] == 2 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 201], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_add(arg, request, obj_1, recipe_1_s1): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'recipe': recipe_1_s1.pk, 'servings': 1}, + content_type='application/json' + ) + response = json.loads(r.content) + print(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['recipe'] == recipe_1_s1.pk + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 173b4a95..9e5cd0ab 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -340,7 +340,7 @@ class ShoppingListRecipeViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsOwner, ] def get_queryset(self): - return self.queryset.filter(shoppinglist__created_by=self.request.user).filter(space=self.request.space).all() + return self.queryset.filter(shoppinglist__created_by=self.request.user, shoppinglist__space=self.request.space).all() class ShoppingListEntryViewSet(viewsets.ModelViewSet): @@ -349,7 +349,7 @@ class ShoppingListEntryViewSet(viewsets.ModelViewSet): permission_classes = [CustomIsOwner, ] def get_queryset(self): - return self.queryset.filter(shoppinglist__created_by=self.request.user).filter(space=self.request.space).all() + return self.queryset.filter(shoppinglist__created_by=self.request.user, shoppinglist__space=self.request.space).all() class ShoppingListViewSet(viewsets.ModelViewSet): From ab3f7bf671506cbeea3a84c6babd531b82525647 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 20:46:49 +0100 Subject: [PATCH 71/96] step api test --- cookbook/tests/api/test_api_step.py | 0 cookbook/tests/pytest/api/test_api_step.py | 106 +++++++++++++++++++++ 2 files changed, 106 insertions(+) delete mode 100644 cookbook/tests/api/test_api_step.py create mode 100644 cookbook/tests/pytest/api/test_api_step.py diff --git a/cookbook/tests/api/test_api_step.py b/cookbook/tests/api/test_api_step.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/pytest/api/test_api_step.py b/cookbook/tests/pytest/api/test_api_step.py new file mode 100644 index 00000000..8d01a0ea --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_step.py @@ -0,0 +1,106 @@ +import json + +import pytest +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import Food, Ingredient, Step + +LIST_URL = 'api:step-list' +DETAIL_URL = 'api:step-detail' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(recipe_1_s1, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + with scopes_disabled(): + recipe_1_s1.space = space_2 + recipe_1_s1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 0 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 2 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], + ['g1_s2', 403], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, recipe_1_s1): + with scopes_disabled(): + s = recipe_1_s1.steps.first() + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={s.id} + ), + {'instruction': 'new'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['instruction'] == 'new' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_add(arg, request, u1_s2): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'instruction': 'test', 'ingredients': []}, + content_type='application/json' + ) + response = json.loads(r.content) + print(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['id'] == 1 + r = c.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 # ingredient is not linked to a recipe and therefore cannot be accessed + r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 + + +def test_delete(u1_s1, u1_s2, recipe_1_s1): + with scopes_disabled(): + s = recipe_1_s1.steps.first() + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={s.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={s.id} + ) + ) + + assert r.status_code == 204 + assert not Step.objects.filter(pk=s.id).exists() From e41464cb310a9891afa9125c53199240a358f3b9 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 20:53:12 +0100 Subject: [PATCH 72/96] recipe api test --- cookbook/tests/api/__init__.py | 0 cookbook/tests/api/test_api_recipe.py | 31 ------ cookbook/tests/pytest/api/test_api_recipe.py | 104 +++++++++++++++++++ 3 files changed, 104 insertions(+), 31 deletions(-) delete mode 100644 cookbook/tests/api/__init__.py delete mode 100644 cookbook/tests/api/test_api_recipe.py create mode 100644 cookbook/tests/pytest/api/test_api_recipe.py diff --git a/cookbook/tests/api/__init__.py b/cookbook/tests/api/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/api/test_api_recipe.py b/cookbook/tests/api/test_api_recipe.py deleted file mode 100644 index 9bd67901..00000000 --- a/cookbook/tests/api/test_api_recipe.py +++ /dev/null @@ -1,31 +0,0 @@ -from cookbook.models import Recipe -from cookbook.tests.views.test_views import TestViews -from django.contrib import auth -from django.urls import reverse - - -class TestApiShopping(TestViews): - - def setUp(self): - super(TestApiShopping, self).setUp() - self.internal_recipe = Recipe.objects.create( - name='Test', - internal=True, - created_by=auth.get_user(self.user_client_1) - ) - - def test_shopping_view_permissions(self): - self.batch_requests( - [ - (self.anonymous_client, 403), - (self.guest_client_1, 200), - (self.user_client_1, 200), - (self.user_client_2, 200), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - reverse( - 'api:recipe-detail', args={self.internal_recipe.id}) - ) - - # TODO add tests for editing diff --git a/cookbook/tests/pytest/api/test_api_recipe.py b/cookbook/tests/pytest/api/test_api_recipe.py new file mode 100644 index 00000000..c1b103ca --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_recipe.py @@ -0,0 +1,104 @@ +import json + +import pytest +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import Food, Ingredient, Step, Recipe + +LIST_URL = 'api:recipe-list' +DETAIL_URL = 'api:recipe-detail' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(recipe_1_s1, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + with scopes_disabled(): + recipe_1_s1.space = space_2 + recipe_1_s1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 0 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 1 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], + ['g1_s2', 404], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, recipe_1_s1): + with scopes_disabled(): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={recipe_1_s1.id} + ), + {'name': 'new'}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == arg[1] + if r.status_code == 200: + assert response['name'] == 'new' + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 201], + ['u1_s1', 201], + ['a1_s1', 201], +]) +def test_add(arg, request, u1_s2): + c = request.getfixturevalue(arg[0]) + r = c.post( + reverse(LIST_URL), + {'name': 'test', 'waiting_time': 0, 'working_time': 0, 'keywords': [], 'steps': []}, + content_type='application/json' + ) + response = json.loads(r.content) + print(r.content) + assert r.status_code == arg[1] + if r.status_code == 201: + assert response['id'] == 1 + r = c.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 200 + r = u1_s2.get(reverse(DETAIL_URL, args={response['id']})) + assert r.status_code == 404 + + +def test_delete(u1_s1, u1_s2, recipe_1_s1): + with scopes_disabled(): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={recipe_1_s1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={recipe_1_s1.id} + ) + ) + + assert r.status_code == 204 + assert not Recipe.objects.filter(pk=recipe_1_s1.id).exists() From ad0d802e411a6ef2c315efc6975aaadcaebc995b Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 21:18:54 +0100 Subject: [PATCH 73/96] more tests --- .idea/recipes.iml | 2 +- cookbook/tests/edits/test_edits_recipe.py | 156 ------------------ cookbook/tests/other/__init__.py | 0 cookbook/tests/other/test_edits_recipe.py | 94 ----------- cookbook/tests/pytest/conftest.py | 3 +- cookbook/tests/pytest/edits/__init__.py | 7 + .../tests/pytest/edits/test_edits_recipe.py | 83 ++++++++++ cookbook/tests/pytest/other/__init__.py | 7 + .../pytest/other/test_ingredient_parser.py | 66 ++++++++ .../tests/pytest/other/test_url_import.py | 30 ++++ .../tests/{ => pytest}/resources/image.jpg | Bin .../tests/{ => pytest}/resources/image.png | Bin .../resources/websites/ld_json_1.html | 0 .../resources/websites/ld_json_2.html | 0 .../resources/websites/ld_json_3.html | 0 .../resources/websites/ld_json_4.html | 0 .../resources/websites/ld_json_itemList.html | 0 .../resources/websites/ld_json_multiple.html | 0 .../resources/websites/micro_data_1.html | 0 .../resources/websites/micro_data_2.html | 0 .../resources/websites/micro_data_3.html | 0 .../resources/websites/micro_data_4.html | 0 cookbook/tests/pytest/test_test.py | 20 --- 23 files changed, 196 insertions(+), 272 deletions(-) delete mode 100644 cookbook/tests/edits/test_edits_recipe.py delete mode 100644 cookbook/tests/other/__init__.py delete mode 100755 cookbook/tests/other/test_edits_recipe.py create mode 100644 cookbook/tests/pytest/edits/__init__.py create mode 100644 cookbook/tests/pytest/edits/test_edits_recipe.py create mode 100644 cookbook/tests/pytest/other/__init__.py create mode 100644 cookbook/tests/pytest/other/test_ingredient_parser.py create mode 100644 cookbook/tests/pytest/other/test_url_import.py rename cookbook/tests/{ => pytest}/resources/image.jpg (100%) rename cookbook/tests/{ => pytest}/resources/image.png (100%) rename cookbook/tests/{ => pytest}/resources/websites/ld_json_1.html (100%) rename cookbook/tests/{ => pytest}/resources/websites/ld_json_2.html (100%) rename cookbook/tests/{ => pytest}/resources/websites/ld_json_3.html (100%) rename cookbook/tests/{ => pytest}/resources/websites/ld_json_4.html (100%) rename cookbook/tests/{ => pytest}/resources/websites/ld_json_itemList.html (100%) rename cookbook/tests/{ => pytest}/resources/websites/ld_json_multiple.html (100%) rename cookbook/tests/{ => pytest}/resources/websites/micro_data_1.html (100%) rename cookbook/tests/{ => pytest}/resources/websites/micro_data_2.html (100%) rename cookbook/tests/{ => pytest}/resources/websites/micro_data_3.html (100%) rename cookbook/tests/{ => pytest}/resources/websites/micro_data_4.html (100%) delete mode 100644 cookbook/tests/pytest/test_test.py diff --git a/.idea/recipes.iml b/.idea/recipes.iml index e1dd7064..e3376610 100644 --- a/.idea/recipes.iml +++ b/.idea/recipes.iml @@ -14,7 +14,7 @@ - + diff --git a/cookbook/tests/edits/test_edits_recipe.py b/cookbook/tests/edits/test_edits_recipe.py deleted file mode 100644 index 0408d001..00000000 --- a/cookbook/tests/edits/test_edits_recipe.py +++ /dev/null @@ -1,156 +0,0 @@ -from cookbook.models import Food, Recipe, Storage, Unit -from cookbook.tests.views.test_views import TestViews -from django.contrib import auth -from django.urls import reverse - - -class TestEditsRecipe(TestViews): - - def test_switch_recipe(self): - internal_recipe = Recipe.objects.create( - name='Test', - internal=True, - created_by=auth.get_user(self.user_client_1) - ) - - external_recipe = Recipe.objects.create( - name='Test', - internal=False, - created_by=auth.get_user(self.user_client_1) - ) - - url = reverse('edit_recipe', args=[internal_recipe.pk]) - r = self.user_client_1.get(url) - self.assertEqual(r.status_code, 302) - - r = self.user_client_1.get(r.url) - self.assertTemplateUsed(r, 'forms/edit_internal_recipe.html') - - url = reverse('edit_recipe', args=[external_recipe.pk]) - r = self.user_client_1.get(url) - self.assertEqual(r.status_code, 302) - - r = self.user_client_1.get(r.url) - self.assertTemplateUsed(r, 'generic/edit_template.html') - - def test_convert_recipe(self): - url = reverse('edit_convert_recipe', args=[42]) - r = self.user_client_1.get(url) - self.assertEqual(r.status_code, 404) - - external_recipe = Recipe.objects.create( - name='Test', - internal=False, - created_by=auth.get_user(self.user_client_1) - ) - - url = reverse('edit_convert_recipe', args=[external_recipe.pk]) - r = self.user_client_1.get(url) - self.assertEqual(r.status_code, 302) - - recipe = Recipe.objects.get(pk=external_recipe.pk) - self.assertTrue(recipe.internal) - - url = reverse('edit_convert_recipe', args=[recipe.pk]) - r = self.user_client_1.get(url) - self.assertEqual(r.status_code, 302) - - def test_internal_recipe_update(self): - recipe = Recipe.objects.create( - name='Test', - created_by=auth.get_user(self.user_client_1) - ) - - url = reverse('api:recipe-detail', args=[recipe.pk]) - - r = self.user_client_1.get(url) - self.assertEqual(r.status_code, 200) - - r = self.anonymous_client.get(url) - self.assertEqual(r.status_code, 403) - - r = self.user_client_1.put( - url, - { - 'name': 'Changed', - 'working_time': 15, - 'waiting_time': 15, - 'keywords': [], - 'steps': [] - }, - content_type='application/json' - ) - self.assertEqual(r.status_code, 200) - - recipe = Recipe.objects.get(pk=recipe.pk) - self.assertEqual('Changed', recipe.name) - - Food.objects.create(name='Egg') - Unit.objects.create(name='g') - - r = self.user_client_1.put( - url, - { - 'name': 'Changed', - 'working_time': 15, - 'waiting_time': 15, - 'keywords': [], - 'steps': [ - { - 'ingredients': [ - { - 'food': {'name': 'test food'}, - 'unit': {'name': 'test unit'}, - 'amount': 12, 'note': 'test note' - }, - { - 'food': {'name': 'test food 2'}, - 'unit': {'name': 'test unit 2'}, - 'amount': 42, 'note': 'test note 2' - } - ] - } - ] - }, - content_type='application/json' - ) - self.assertEqual(r.status_code, 200) - self.assertEqual(2, recipe.steps.first().ingredients.count()) - - with open('cookbook/tests/resources/image.jpg', 'rb') as file: # noqa: E501,F841 - pass # TODO new image tests - - with open('cookbook/tests/resources/image.png', 'rb') as file: # noqa: E501,F841 - pass # TODO new image tests - - def test_external_recipe_update(self): - storage = Storage.objects.create( - name='TestStorage', - method=Storage.DROPBOX, - created_by=auth.get_user(self.user_client_1), - token='test', - username='test', - password='test', - ) - - recipe = Recipe.objects.create( - name='Test', - created_by=auth.get_user(self.user_client_1), - storage=storage, - ) - - url = reverse('edit_external_recipe', args=[recipe.pk]) - - r = self.user_client_1.get(url) - self.assertEqual(r.status_code, 200) - - r = self.anonymous_client.get(url) - self.assertEqual(r.status_code, 302) - - r = self.user_client_1.post( - url, - {'name': 'Test', 'working_time': 15, 'waiting_time': 15, 'servings': 1, } - ) - recipe.refresh_from_db() - self.assertEqual(recipe.working_time, 15) - self.assertEqual(recipe.waiting_time, 15) diff --git a/cookbook/tests/other/__init__.py b/cookbook/tests/other/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cookbook/tests/other/test_edits_recipe.py b/cookbook/tests/other/test_edits_recipe.py deleted file mode 100755 index 6ee20013..00000000 --- a/cookbook/tests/other/test_edits_recipe.py +++ /dev/null @@ -1,94 +0,0 @@ -import json - -from cookbook.helper.ingredient_parser import parse -from cookbook.helper.recipe_url_import import get_from_html -from cookbook.tests.test_setup import TestBase - - -class TestEditsRecipe(TestBase): - - # flake8: noqa - def test_ld_json(self): - test_list = [ - {'file': 'cookbook/tests/resources/websites/ld_json_1.html', 'result_length': 3237}, - {'file': 'cookbook/tests/resources/websites/ld_json_2.html', 'result_length': 1525}, - {'file': 'cookbook/tests/resources/websites/ld_json_3.html', 'result_length': 1644}, - {'file': 'cookbook/tests/resources/websites/ld_json_4.html', 'result_length': 1744}, - {'file': 'cookbook/tests/resources/websites/ld_json_itemList.html', 'result_length': 3222}, - {'file': 'cookbook/tests/resources/websites/ld_json_multiple.html', 'result_length': 1621}, - {'file': 'cookbook/tests/resources/websites/micro_data_1.html', 'result_length': 1094}, - {'file': 'cookbook/tests/resources/websites/micro_data_2.html', 'result_length': 1453}, - {'file': 'cookbook/tests/resources/websites/micro_data_3.html', 'result_length': 1163}, - {'file': 'cookbook/tests/resources/websites/micro_data_4.html', 'result_length': 4411}, - ] - - for test in test_list: - with open(test['file'], 'rb') as file: - print(f'Testing {test["file"]} expecting length {test["result_length"]}') - parsed_content = json.loads(get_from_html(file.read(), 'test_url', None).content) - self.assertEqual(len(str(parsed_content)), test['result_length']) - file.close() - - def test_ingredient_parser(self): - expectations = { - "2¼ l Wasser": (2.25, "l", "Wasser", ""), - "2¼l Wasser": (2.25, "l", "Wasser", ""), - "¼ l Wasser": (0.25, "l", "Wasser", ""), - "3l Wasser": (3, "l", "Wasser", ""), - "4 l Wasser": (4, "l", "Wasser", ""), - "½l Wasser": (0.5, "l", "Wasser", ""), - "⅛ Liter Sauerrahm": (0.125, "Liter", "Sauerrahm", ""), - "5 Zwiebeln": (5, "", "Zwiebeln", ""), - "3 Zwiebeln, gehackt": (3, "", "Zwiebeln", "gehackt"), - "5 Zwiebeln (gehackt)": (5, "", "Zwiebeln", "gehackt"), - "1 Zwiebel(n)": (1, "", "Zwiebel(n)", ""), - "4 1/2 Zwiebeln": (4.5, "", "Zwiebeln", ""), - "4 ½ Zwiebeln": (4.5, "", "Zwiebeln", ""), - "1/2 EL Mehl": (0.5, "EL", "Mehl", ""), - "1/2 Zwiebel": (0.5, "", "Zwiebel", ""), - "1/5g Mehl, gesiebt": (0.2, "g", "Mehl", "gesiebt"), - "1/2 Zitrone, ausgepresst": (0.5, "", "Zitrone", "ausgepresst"), - "etwas Mehl": (0, "", "etwas Mehl", ""), - "Öl zum Anbraten": (0, "", "Öl zum Anbraten", ""), - "n. B. Knoblauch, zerdrückt": (0, "", "n. B. Knoblauch", "zerdrückt"), - "Kräuter, mediterrane (Oregano, Rosmarin, Basilikum)": ( - 0, "", "Kräuter, mediterrane", "Oregano, Rosmarin, Basilikum"), - "600 g Kürbisfleisch (Hokkaido), geschält, entkernt und geraspelt": ( - 600, "g", "Kürbisfleisch (Hokkaido)", "geschält, entkernt und geraspelt"), - "Muskat": (0, "", "Muskat", ""), - "200 g Mehl, glattes": (200, "g", "Mehl", "glattes"), - "1 Ei(er)": (1, "", "Ei(er)", ""), - "1 Prise(n) Salz": (1, "Prise(n)", "Salz", ""), - "etwas Wasser, lauwarmes": (0, "", "etwas Wasser", "lauwarmes"), - "Strudelblätter, fertige, für zwei Strudel": (0, "", "Strudelblätter", "fertige, für zwei Strudel"), - "barrel-aged Bourbon": (0, "", "barrel-aged Bourbon", ""), - "golden syrup": (0, "", "golden syrup", ""), - "unsalted butter, for greasing": (0, "", "unsalted butter", "for greasing"), - "unsalted butter , for greasing": (0, "", "unsalted butter", "for greasing"), # trim - "1 small sprig of fresh rosemary": (1, "small", "sprig of fresh rosemary", ""), - # does not always work perfectly! - "75 g fresh breadcrumbs": (75, "g", "fresh breadcrumbs", ""), - "4 acorn squash , or onion squash (600-800g)": (4, "acorn", "squash , or onion squash", "600-800g"), - "1 x 250 g packet of cooked mixed grains , such as spelt and wild rice": ( - 1, "x", "250 g packet of cooked mixed grains", "such as spelt and wild rice"), - "1 big bunch of fresh mint , (60g)": (1, "big", "bunch of fresh mint ,", "60g"), - "1 large red onion": (1, "large", "red onion", ""), - # "2-3 TL Curry": (), # idk what it should use here either - "1 Zwiebel gehackt": (1, "Zwiebel", "gehackt", ""), - "1 EL Kokosöl": (1, "EL", "Kokosöl", ""), - "0.5 paket jäst (à 50 g)": (0.5, "paket", "jäst", "à 50 g"), - "ägg": (0, "", "ägg", ""), - "50 g smör eller margarin": (50, "g", "smör eller margarin", ""), - "3,5 l Wasser": (3.5, "l", "Wasser", ""), - "3.5 l Wasser": (3.5, "l", "Wasser", ""), - "400 g Karotte(n)": (400, "g", "Karotte(n)", "") - } - # for German you could say that if an ingredient does not have - # an amount # and it starts with a lowercase letter, then that - # is a unit ("etwas", "evtl.") does not apply to English tho - - count = 0 - for key, val in expectations.items(): - count += 1 - parsed = parse(key) - self.assertEqual(val, parsed) diff --git a/cookbook/tests/pytest/conftest.py b/cookbook/tests/pytest/conftest.py index c9ffc423..24b1f9a6 100644 --- a/cookbook/tests/pytest/conftest.py +++ b/cookbook/tests/pytest/conftest.py @@ -47,7 +47,8 @@ def get_random_recipe(space_1, u1_s1): working_time=20, servings=4, created_by=auth.get_user(u1_s1), - space=space_1 + space=space_1, + internal=True, ) s1 = Step.objects.create(name=uuid.uuid4(), instruction=uuid.uuid4(), ) diff --git a/cookbook/tests/pytest/edits/__init__.py b/cookbook/tests/pytest/edits/__init__.py new file mode 100644 index 00000000..cd886345 --- /dev/null +++ b/cookbook/tests/pytest/edits/__init__.py @@ -0,0 +1,7 @@ +from django.test import utils +from django_scopes import scopes_disabled + +# disables scoping error in all queries used inside the test FUNCTIONS +# FIXTURES need to have their own scopes_disabled!! +# This is done by hook pytest_fixture_setup in conftest.py for all non yield fixtures +utils.setup_databases = scopes_disabled()(utils.setup_databases) diff --git a/cookbook/tests/pytest/edits/test_edits_recipe.py b/cookbook/tests/pytest/edits/test_edits_recipe.py new file mode 100644 index 00000000..894a8d5c --- /dev/null +++ b/cookbook/tests/pytest/edits/test_edits_recipe.py @@ -0,0 +1,83 @@ +from cookbook.models import Food, Recipe, Storage, Unit +from cookbook.tests.views.test_views import TestViews +from django.contrib import auth +from django.urls import reverse +from pytest_django.asserts import assertTemplateUsed + + +def test_switch_recipe(u1_s1, recipe_1_s1, space_1): + external_recipe = Recipe.objects.create( + name='Test', + internal=False, + created_by=auth.get_user(u1_s1), + space=space_1, + ) + + url = reverse('edit_recipe', args=[recipe_1_s1.pk]) + r = u1_s1.get(url) + assert r.status_code == 302 + + r = u1_s1.get(r.url) + assertTemplateUsed(r, 'forms/edit_internal_recipe.html') + + url = reverse('edit_recipe', args=[external_recipe.pk]) + r = u1_s1.get(url) + assert r.status_code == 302 + + r = u1_s1.get(r.url) + assertTemplateUsed(r, 'generic/edit_template.html') + + +def test_convert_recipe(u1_s1, space_1): + external_recipe = Recipe.objects.create( + name='Test', + internal=False, + created_by=auth.get_user(u1_s1), + space=space_1, + ) + + r = u1_s1.get(reverse('edit_convert_recipe', args=[external_recipe.pk])) + assert r.status_code == 302 + + external_recipe.refresh_from_db() + assert external_recipe.internal + + +def test_external_recipe_update(u1_s1, u1_s2, space_1): + storage = Storage.objects.create( + name='TestStorage', + method=Storage.DROPBOX, + created_by=auth.get_user(u1_s1), + token='test', + username='test', + password='test', + space=space_1, + ) + + recipe = Recipe.objects.create( + name='Test', + created_by=auth.get_user(u1_s1), + storage=storage, + space=space_1, + ) + + url = reverse('edit_external_recipe', args=[recipe.pk]) + + r = u1_s1.get(url) + assert r.status_code == 200 + + u1_s2.post( + url, + {'name': 'Test', 'working_time': 15, 'waiting_time': 15, 'servings': 1, } + ) + recipe.refresh_from_db() + assert recipe.working_time == 0 + assert recipe.waiting_time == 0 + + u1_s1.post( + url, + {'name': 'Test', 'working_time': 15, 'waiting_time': 15, 'servings': 1, } + ) + recipe.refresh_from_db() + assert recipe.working_time == 15 + assert recipe.waiting_time == 15 diff --git a/cookbook/tests/pytest/other/__init__.py b/cookbook/tests/pytest/other/__init__.py new file mode 100644 index 00000000..cd886345 --- /dev/null +++ b/cookbook/tests/pytest/other/__init__.py @@ -0,0 +1,7 @@ +from django.test import utils +from django_scopes import scopes_disabled + +# disables scoping error in all queries used inside the test FUNCTIONS +# FIXTURES need to have their own scopes_disabled!! +# This is done by hook pytest_fixture_setup in conftest.py for all non yield fixtures +utils.setup_databases = scopes_disabled()(utils.setup_databases) diff --git a/cookbook/tests/pytest/other/test_ingredient_parser.py b/cookbook/tests/pytest/other/test_ingredient_parser.py new file mode 100644 index 00000000..076df4b0 --- /dev/null +++ b/cookbook/tests/pytest/other/test_ingredient_parser.py @@ -0,0 +1,66 @@ +from cookbook.helper.ingredient_parser import parse + + +def test_ingredient_parser(): + expectations = { + "2¼ l Wasser": (2.25, "l", "Wasser", ""), + "2¼l Wasser": (2.25, "l", "Wasser", ""), + "¼ l Wasser": (0.25, "l", "Wasser", ""), + "3l Wasser": (3, "l", "Wasser", ""), + "4 l Wasser": (4, "l", "Wasser", ""), + "½l Wasser": (0.5, "l", "Wasser", ""), + "⅛ Liter Sauerrahm": (0.125, "Liter", "Sauerrahm", ""), + "5 Zwiebeln": (5, "", "Zwiebeln", ""), + "3 Zwiebeln, gehackt": (3, "", "Zwiebeln", "gehackt"), + "5 Zwiebeln (gehackt)": (5, "", "Zwiebeln", "gehackt"), + "1 Zwiebel(n)": (1, "", "Zwiebel(n)", ""), + "4 1/2 Zwiebeln": (4.5, "", "Zwiebeln", ""), + "4 ½ Zwiebeln": (4.5, "", "Zwiebeln", ""), + "1/2 EL Mehl": (0.5, "EL", "Mehl", ""), + "1/2 Zwiebel": (0.5, "", "Zwiebel", ""), + "1/5g Mehl, gesiebt": (0.2, "g", "Mehl", "gesiebt"), + "1/2 Zitrone, ausgepresst": (0.5, "", "Zitrone", "ausgepresst"), + "etwas Mehl": (0, "", "etwas Mehl", ""), + "Öl zum Anbraten": (0, "", "Öl zum Anbraten", ""), + "n. B. Knoblauch, zerdrückt": (0, "", "n. B. Knoblauch", "zerdrückt"), + "Kräuter, mediterrane (Oregano, Rosmarin, Basilikum)": ( + 0, "", "Kräuter, mediterrane", "Oregano, Rosmarin, Basilikum"), + "600 g Kürbisfleisch (Hokkaido), geschält, entkernt und geraspelt": ( + 600, "g", "Kürbisfleisch (Hokkaido)", "geschält, entkernt und geraspelt"), + "Muskat": (0, "", "Muskat", ""), + "200 g Mehl, glattes": (200, "g", "Mehl", "glattes"), + "1 Ei(er)": (1, "", "Ei(er)", ""), + "1 Prise(n) Salz": (1, "Prise(n)", "Salz", ""), + "etwas Wasser, lauwarmes": (0, "", "etwas Wasser", "lauwarmes"), + "Strudelblätter, fertige, für zwei Strudel": (0, "", "Strudelblätter", "fertige, für zwei Strudel"), + "barrel-aged Bourbon": (0, "", "barrel-aged Bourbon", ""), + "golden syrup": (0, "", "golden syrup", ""), + "unsalted butter, for greasing": (0, "", "unsalted butter", "for greasing"), + "unsalted butter , for greasing": (0, "", "unsalted butter", "for greasing"), # trim + "1 small sprig of fresh rosemary": (1, "small", "sprig of fresh rosemary", ""), + # does not always work perfectly! + "75 g fresh breadcrumbs": (75, "g", "fresh breadcrumbs", ""), + "4 acorn squash , or onion squash (600-800g)": (4, "acorn", "squash , or onion squash", "600-800g"), + "1 x 250 g packet of cooked mixed grains , such as spelt and wild rice": ( + 1, "x", "250 g packet of cooked mixed grains", "such as spelt and wild rice"), + "1 big bunch of fresh mint , (60g)": (1, "big", "bunch of fresh mint ,", "60g"), + "1 large red onion": (1, "large", "red onion", ""), + # "2-3 TL Curry": (), # idk what it should use here either + "1 Zwiebel gehackt": (1, "Zwiebel", "gehackt", ""), + "1 EL Kokosöl": (1, "EL", "Kokosöl", ""), + "0.5 paket jäst (à 50 g)": (0.5, "paket", "jäst", "à 50 g"), + "ägg": (0, "", "ägg", ""), + "50 g smör eller margarin": (50, "g", "smör eller margarin", ""), + "3,5 l Wasser": (3.5, "l", "Wasser", ""), + "3.5 l Wasser": (3.5, "l", "Wasser", ""), + "400 g Karotte(n)": (400, "g", "Karotte(n)", "") + } + # for German you could say that if an ingredient does not have + # an amount # and it starts with a lowercase letter, then that + # is a unit ("etwas", "evtl.") does not apply to English tho + + count = 0 + for key, val in expectations.items(): + count += 1 + parsed = parse(key) + assert val == parsed diff --git a/cookbook/tests/pytest/other/test_url_import.py b/cookbook/tests/pytest/other/test_url_import.py new file mode 100644 index 00000000..a82d012f --- /dev/null +++ b/cookbook/tests/pytest/other/test_url_import.py @@ -0,0 +1,30 @@ +import json + +from django_scopes import scopes_disabled + +from cookbook.helper.ingredient_parser import parse +from cookbook.helper.recipe_url_import import get_from_html +from cookbook.tests.test_setup import TestBase + + +def test_ld_json(): + with scopes_disabled(): + test_list = [ + {'file': '../resources/websites/ld_json_1.html', 'result_length': 3237}, + {'file': '../resources/websites/ld_json_2.html', 'result_length': 1525}, + {'file': '../resources/websites/ld_json_3.html', 'result_length': 1644}, + {'file': '../resources/websites/ld_json_4.html', 'result_length': 1744}, + {'file': '../resources/websites/ld_json_itemList.html', 'result_length': 3222}, + {'file': '../resources/websites/ld_json_multiple.html', 'result_length': 1621}, + {'file': '../resources/websites/micro_data_1.html', 'result_length': 1094}, + {'file': '../resources/websites/micro_data_2.html', 'result_length': 1453}, + {'file': '../resources/websites/micro_data_3.html', 'result_length': 1163}, + {'file': '../resources/websites/micro_data_4.html', 'result_length': 4411}, + ] + + for test in test_list: + with open(test['file'], 'rb') as file: + print(f'Testing {test["file"]} expecting length {test["result_length"]}') + parsed_content = json.loads(get_from_html(file.read(), 'test_url', None).content) + assert len(str(parsed_content)) == test['result_length'] + file.close() diff --git a/cookbook/tests/resources/image.jpg b/cookbook/tests/pytest/resources/image.jpg similarity index 100% rename from cookbook/tests/resources/image.jpg rename to cookbook/tests/pytest/resources/image.jpg diff --git a/cookbook/tests/resources/image.png b/cookbook/tests/pytest/resources/image.png similarity index 100% rename from cookbook/tests/resources/image.png rename to cookbook/tests/pytest/resources/image.png diff --git a/cookbook/tests/resources/websites/ld_json_1.html b/cookbook/tests/pytest/resources/websites/ld_json_1.html similarity index 100% rename from cookbook/tests/resources/websites/ld_json_1.html rename to cookbook/tests/pytest/resources/websites/ld_json_1.html diff --git a/cookbook/tests/resources/websites/ld_json_2.html b/cookbook/tests/pytest/resources/websites/ld_json_2.html similarity index 100% rename from cookbook/tests/resources/websites/ld_json_2.html rename to cookbook/tests/pytest/resources/websites/ld_json_2.html diff --git a/cookbook/tests/resources/websites/ld_json_3.html b/cookbook/tests/pytest/resources/websites/ld_json_3.html similarity index 100% rename from cookbook/tests/resources/websites/ld_json_3.html rename to cookbook/tests/pytest/resources/websites/ld_json_3.html diff --git a/cookbook/tests/resources/websites/ld_json_4.html b/cookbook/tests/pytest/resources/websites/ld_json_4.html similarity index 100% rename from cookbook/tests/resources/websites/ld_json_4.html rename to cookbook/tests/pytest/resources/websites/ld_json_4.html diff --git a/cookbook/tests/resources/websites/ld_json_itemList.html b/cookbook/tests/pytest/resources/websites/ld_json_itemList.html similarity index 100% rename from cookbook/tests/resources/websites/ld_json_itemList.html rename to cookbook/tests/pytest/resources/websites/ld_json_itemList.html diff --git a/cookbook/tests/resources/websites/ld_json_multiple.html b/cookbook/tests/pytest/resources/websites/ld_json_multiple.html similarity index 100% rename from cookbook/tests/resources/websites/ld_json_multiple.html rename to cookbook/tests/pytest/resources/websites/ld_json_multiple.html diff --git a/cookbook/tests/resources/websites/micro_data_1.html b/cookbook/tests/pytest/resources/websites/micro_data_1.html similarity index 100% rename from cookbook/tests/resources/websites/micro_data_1.html rename to cookbook/tests/pytest/resources/websites/micro_data_1.html diff --git a/cookbook/tests/resources/websites/micro_data_2.html b/cookbook/tests/pytest/resources/websites/micro_data_2.html similarity index 100% rename from cookbook/tests/resources/websites/micro_data_2.html rename to cookbook/tests/pytest/resources/websites/micro_data_2.html diff --git a/cookbook/tests/resources/websites/micro_data_3.html b/cookbook/tests/pytest/resources/websites/micro_data_3.html similarity index 100% rename from cookbook/tests/resources/websites/micro_data_3.html rename to cookbook/tests/pytest/resources/websites/micro_data_3.html diff --git a/cookbook/tests/resources/websites/micro_data_4.html b/cookbook/tests/pytest/resources/websites/micro_data_4.html similarity index 100% rename from cookbook/tests/resources/websites/micro_data_4.html rename to cookbook/tests/pytest/resources/websites/micro_data_4.html diff --git a/cookbook/tests/pytest/test_test.py b/cookbook/tests/pytest/test_test.py deleted file mode 100644 index 69894b63..00000000 --- a/cookbook/tests/pytest/test_test.py +++ /dev/null @@ -1,20 +0,0 @@ -import json - -import pytest - -from django.contrib.auth.models import User -from django.urls import reverse -from django_scopes import scopes_disabled - -from cookbook.models import Keyword, Space - - -@pytest.mark.django_db -def test_user_create(u1_s1,u1_s2): - r = u1_s1.post(reverse('api:keyword-list'), {'name': 'test', 'space': 1}, content_type='application/json') - response = json.loads(r.content) - assert r.status_code == 201 - assert response['name'] == 'test' - - r = u1_s2.get(reverse('api:keyword-detail', args={response['id']}), content_type='application/json') - assert r.status_code == 404 From 76eeed1a77a20127eb178da0c8f53f43b53ae758 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 22:10:58 +0100 Subject: [PATCH 74/96] all tests migrated and improved --- .idea/recipes.iml | 2 +- cookbook/tests/{pytest => api}/__init__.py | 0 .../{pytest => }/api/test_api_cook_log.py | 0 .../tests/{pytest => }/api/test_api_food.py | 0 .../{pytest => }/api/test_api_ingredient.py | 0 .../{pytest => }/api/test_api_keyword.py | 0 .../{pytest => }/api/test_api_meal_plan.py | 0 .../{pytest => }/api/test_api_meal_type.py | 0 .../tests/{pytest => }/api/test_api_recipe.py | 0 .../{pytest => }/api/test_api_recipe_book.py | 0 .../api/test_api_recipe_book_entry.py | 0 .../api/test_api_shopping_list.py | 0 .../api/test_api_shopping_list_entry.py | 0 .../api/test_api_shopping_list_recipe.py | 0 .../tests/{pytest => }/api/test_api_step.py | 0 .../{pytest => }/api/test_api_storage.py | 0 .../{pytest => }/api/test_api_supermarket.py | 0 .../tests/{pytest => }/api/test_api_sync.py | 0 .../{pytest => }/api/test_api_sync_log.py | 0 .../tests/{pytest => }/api/test_api_unit.py | 0 .../{pytest => }/api/test_api_username.py | 1 - .../api/test_api_userpreference.py | 7 - .../{pytest => }/api/test_api_view_log.py | 0 cookbook/tests/{pytest => }/conftest.py | 19 +- cookbook/tests/edits/__init__.py | 7 + cookbook/tests/edits/test_edits_comment.py | 57 ----- .../{pytest => }/edits/test_edits_recipe.py | 3 +- cookbook/tests/edits/test_edits_storage.py | 106 ++++---- .../tests/{pytest/api => other}/__init__.py | 0 .../other/test_ingredient_parser.py | 0 cookbook/tests/other/test_url_import.py | 28 +++ cookbook/tests/pytest/edits/__init__.py | 7 - cookbook/tests/pytest/other/__init__.py | 7 - .../tests/pytest/other/test_url_import.py | 30 --- .../tests/{pytest => }/resources/image.jpg | Bin .../tests/{pytest => }/resources/image.png | Bin .../resources/websites/ld_json_1.html | 0 .../resources/websites/ld_json_2.html | 0 .../resources/websites/ld_json_3.html | 0 .../resources/websites/ld_json_4.html | 0 .../resources/websites/ld_json_itemList.html | 0 .../resources/websites/ld_json_multiple.html | 0 .../resources/websites/micro_data_1.html | 0 .../resources/websites/micro_data_2.html | 0 .../resources/websites/micro_data_3.html | 0 .../resources/websites/micro_data_4.html | 0 cookbook/tests/test_setup.py | 70 ------ cookbook/tests/views/__init__.py | 7 + cookbook/tests/views/test_views.py | 5 - cookbook/tests/views/test_views_api.py | 61 ++--- cookbook/tests/views/test_views_general.py | 227 ++++++++---------- .../tests/views/test_views_recipe_share.py | 59 ++--- cookbook/views/api.py | 6 +- 53 files changed, 266 insertions(+), 443 deletions(-) rename cookbook/tests/{pytest => api}/__init__.py (100%) rename cookbook/tests/{pytest => }/api/test_api_cook_log.py (100%) rename cookbook/tests/{pytest => }/api/test_api_food.py (100%) rename cookbook/tests/{pytest => }/api/test_api_ingredient.py (100%) rename cookbook/tests/{pytest => }/api/test_api_keyword.py (100%) rename cookbook/tests/{pytest => }/api/test_api_meal_plan.py (100%) rename cookbook/tests/{pytest => }/api/test_api_meal_type.py (100%) rename cookbook/tests/{pytest => }/api/test_api_recipe.py (100%) rename cookbook/tests/{pytest => }/api/test_api_recipe_book.py (100%) rename cookbook/tests/{pytest => }/api/test_api_recipe_book_entry.py (100%) rename cookbook/tests/{pytest => }/api/test_api_shopping_list.py (100%) rename cookbook/tests/{pytest => }/api/test_api_shopping_list_entry.py (100%) rename cookbook/tests/{pytest => }/api/test_api_shopping_list_recipe.py (100%) rename cookbook/tests/{pytest => }/api/test_api_step.py (100%) rename cookbook/tests/{pytest => }/api/test_api_storage.py (100%) rename cookbook/tests/{pytest => }/api/test_api_supermarket.py (100%) rename cookbook/tests/{pytest => }/api/test_api_sync.py (100%) rename cookbook/tests/{pytest => }/api/test_api_sync_log.py (100%) rename cookbook/tests/{pytest => }/api/test_api_unit.py (100%) rename cookbook/tests/{pytest => }/api/test_api_username.py (97%) rename cookbook/tests/{pytest => }/api/test_api_userpreference.py (94%) rename cookbook/tests/{pytest => }/api/test_api_view_log.py (100%) rename cookbook/tests/{pytest => }/conftest.py (89%) delete mode 100644 cookbook/tests/edits/test_edits_comment.py rename cookbook/tests/{pytest => }/edits/test_edits_recipe.py (95%) rename cookbook/tests/{pytest/api => other}/__init__.py (100%) rename cookbook/tests/{pytest => }/other/test_ingredient_parser.py (100%) create mode 100644 cookbook/tests/other/test_url_import.py delete mode 100644 cookbook/tests/pytest/edits/__init__.py delete mode 100644 cookbook/tests/pytest/other/__init__.py delete mode 100644 cookbook/tests/pytest/other/test_url_import.py rename cookbook/tests/{pytest => }/resources/image.jpg (100%) rename cookbook/tests/{pytest => }/resources/image.png (100%) rename cookbook/tests/{pytest => }/resources/websites/ld_json_1.html (100%) rename cookbook/tests/{pytest => }/resources/websites/ld_json_2.html (100%) rename cookbook/tests/{pytest => }/resources/websites/ld_json_3.html (100%) rename cookbook/tests/{pytest => }/resources/websites/ld_json_4.html (100%) rename cookbook/tests/{pytest => }/resources/websites/ld_json_itemList.html (100%) rename cookbook/tests/{pytest => }/resources/websites/ld_json_multiple.html (100%) rename cookbook/tests/{pytest => }/resources/websites/micro_data_1.html (100%) rename cookbook/tests/{pytest => }/resources/websites/micro_data_2.html (100%) rename cookbook/tests/{pytest => }/resources/websites/micro_data_3.html (100%) rename cookbook/tests/{pytest => }/resources/websites/micro_data_4.html (100%) delete mode 100644 cookbook/tests/test_setup.py delete mode 100644 cookbook/tests/views/test_views.py diff --git a/.idea/recipes.iml b/.idea/recipes.iml index e3376610..e1dd7064 100644 --- a/.idea/recipes.iml +++ b/.idea/recipes.iml @@ -14,7 +14,7 @@ - + diff --git a/cookbook/tests/pytest/__init__.py b/cookbook/tests/api/__init__.py similarity index 100% rename from cookbook/tests/pytest/__init__.py rename to cookbook/tests/api/__init__.py diff --git a/cookbook/tests/pytest/api/test_api_cook_log.py b/cookbook/tests/api/test_api_cook_log.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_cook_log.py rename to cookbook/tests/api/test_api_cook_log.py diff --git a/cookbook/tests/pytest/api/test_api_food.py b/cookbook/tests/api/test_api_food.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_food.py rename to cookbook/tests/api/test_api_food.py diff --git a/cookbook/tests/pytest/api/test_api_ingredient.py b/cookbook/tests/api/test_api_ingredient.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_ingredient.py rename to cookbook/tests/api/test_api_ingredient.py diff --git a/cookbook/tests/pytest/api/test_api_keyword.py b/cookbook/tests/api/test_api_keyword.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_keyword.py rename to cookbook/tests/api/test_api_keyword.py diff --git a/cookbook/tests/pytest/api/test_api_meal_plan.py b/cookbook/tests/api/test_api_meal_plan.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_meal_plan.py rename to cookbook/tests/api/test_api_meal_plan.py diff --git a/cookbook/tests/pytest/api/test_api_meal_type.py b/cookbook/tests/api/test_api_meal_type.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_meal_type.py rename to cookbook/tests/api/test_api_meal_type.py diff --git a/cookbook/tests/pytest/api/test_api_recipe.py b/cookbook/tests/api/test_api_recipe.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_recipe.py rename to cookbook/tests/api/test_api_recipe.py diff --git a/cookbook/tests/pytest/api/test_api_recipe_book.py b/cookbook/tests/api/test_api_recipe_book.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_recipe_book.py rename to cookbook/tests/api/test_api_recipe_book.py diff --git a/cookbook/tests/pytest/api/test_api_recipe_book_entry.py b/cookbook/tests/api/test_api_recipe_book_entry.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_recipe_book_entry.py rename to cookbook/tests/api/test_api_recipe_book_entry.py diff --git a/cookbook/tests/pytest/api/test_api_shopping_list.py b/cookbook/tests/api/test_api_shopping_list.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_shopping_list.py rename to cookbook/tests/api/test_api_shopping_list.py diff --git a/cookbook/tests/pytest/api/test_api_shopping_list_entry.py b/cookbook/tests/api/test_api_shopping_list_entry.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_shopping_list_entry.py rename to cookbook/tests/api/test_api_shopping_list_entry.py diff --git a/cookbook/tests/pytest/api/test_api_shopping_list_recipe.py b/cookbook/tests/api/test_api_shopping_list_recipe.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_shopping_list_recipe.py rename to cookbook/tests/api/test_api_shopping_list_recipe.py diff --git a/cookbook/tests/pytest/api/test_api_step.py b/cookbook/tests/api/test_api_step.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_step.py rename to cookbook/tests/api/test_api_step.py diff --git a/cookbook/tests/pytest/api/test_api_storage.py b/cookbook/tests/api/test_api_storage.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_storage.py rename to cookbook/tests/api/test_api_storage.py diff --git a/cookbook/tests/pytest/api/test_api_supermarket.py b/cookbook/tests/api/test_api_supermarket.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_supermarket.py rename to cookbook/tests/api/test_api_supermarket.py diff --git a/cookbook/tests/pytest/api/test_api_sync.py b/cookbook/tests/api/test_api_sync.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_sync.py rename to cookbook/tests/api/test_api_sync.py diff --git a/cookbook/tests/pytest/api/test_api_sync_log.py b/cookbook/tests/api/test_api_sync_log.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_sync_log.py rename to cookbook/tests/api/test_api_sync_log.py diff --git a/cookbook/tests/pytest/api/test_api_unit.py b/cookbook/tests/api/test_api_unit.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_unit.py rename to cookbook/tests/api/test_api_unit.py diff --git a/cookbook/tests/pytest/api/test_api_username.py b/cookbook/tests/api/test_api_username.py similarity index 97% rename from cookbook/tests/pytest/api/test_api_username.py rename to cookbook/tests/api/test_api_username.py index 0e4b137d..c545003a 100644 --- a/cookbook/tests/pytest/api/test_api_username.py +++ b/cookbook/tests/api/test_api_username.py @@ -2,7 +2,6 @@ import json import pytest -from cookbook.tests.views.test_views import TestViews from django.contrib import auth from django.urls import reverse diff --git a/cookbook/tests/pytest/api/test_api_userpreference.py b/cookbook/tests/api/test_api_userpreference.py similarity index 94% rename from cookbook/tests/pytest/api/test_api_userpreference.py rename to cookbook/tests/api/test_api_userpreference.py index 3f819e93..31bf7faf 100644 --- a/cookbook/tests/pytest/api/test_api_userpreference.py +++ b/cookbook/tests/api/test_api_userpreference.py @@ -1,9 +1,4 @@ -import json - from cookbook.models import UserPreference -from cookbook.tests.views.test_views import TestViews -from django.contrib import auth -from django.urls import reverse import json @@ -12,8 +7,6 @@ from django.contrib import auth from django.urls import reverse from django_scopes import scopes_disabled -from cookbook.models import RecipeBook, RecipeBookEntry - LIST_URL = 'api:userpreference-list' DETAIL_URL = 'api:userpreference-detail' diff --git a/cookbook/tests/pytest/api/test_api_view_log.py b/cookbook/tests/api/test_api_view_log.py similarity index 100% rename from cookbook/tests/pytest/api/test_api_view_log.py rename to cookbook/tests/api/test_api_view_log.py diff --git a/cookbook/tests/pytest/conftest.py b/cookbook/tests/conftest.py similarity index 89% rename from cookbook/tests/pytest/conftest.py rename to cookbook/tests/conftest.py index 24b1f9a6..8ab9dc51 100644 --- a/cookbook/tests/pytest/conftest.py +++ b/cookbook/tests/conftest.py @@ -7,7 +7,7 @@ from django.contrib import auth from django.contrib.auth.models import User, Group from django_scopes import scopes_disabled -from cookbook.models import Space, Recipe, Step, Ingredient, Food, Unit +from cookbook.models import Space, Recipe, Step, Ingredient, Food, Unit, Storage # hack from https://github.com/raphaelm/django-scopes to disable scopes for all fixtures @@ -61,8 +61,8 @@ def get_random_recipe(space_1, u1_s1): s1.ingredients.add( Ingredient.objects.create( amount=1, - food=Food.objects.create(name=uuid.uuid4(), space=space_1,), - unit=Unit.objects.create(name=uuid.uuid4(), space=space_1,), + food=Food.objects.create(name=uuid.uuid4(), space=space_1, ), + unit=Unit.objects.create(name=uuid.uuid4(), space=space_1, ), note=uuid.uuid4(), ) ) @@ -70,8 +70,8 @@ def get_random_recipe(space_1, u1_s1): s2.ingredients.add( Ingredient.objects.create( amount=1, - food=Food.objects.create(name=uuid.uuid4(), space=space_1,), - unit=Unit.objects.create(name=uuid.uuid4(), space=space_1,), + food=Food.objects.create(name=uuid.uuid4(), space=space_1, ), + unit=Unit.objects.create(name=uuid.uuid4(), space=space_1, ), note=uuid.uuid4(), ) ) @@ -89,6 +89,15 @@ def recipe_2_s1(space_1, u1_s1): return get_random_recipe(space_1, u1_s1) +@pytest.fixture +def ext_recipe_1_s1(space_1, u1_s1): + r = get_random_recipe(space_1, u1_s1) + r.internal = False + r.link = 'test' + r.save() + return r + + # ---------------------- USER FIXTURES ----------------------- # maybe better with factories but this is very explict so ... diff --git a/cookbook/tests/edits/__init__.py b/cookbook/tests/edits/__init__.py index e69de29b..cd886345 100644 --- a/cookbook/tests/edits/__init__.py +++ b/cookbook/tests/edits/__init__.py @@ -0,0 +1,7 @@ +from django.test import utils +from django_scopes import scopes_disabled + +# disables scoping error in all queries used inside the test FUNCTIONS +# FIXTURES need to have their own scopes_disabled!! +# This is done by hook pytest_fixture_setup in conftest.py for all non yield fixtures +utils.setup_databases = scopes_disabled()(utils.setup_databases) diff --git a/cookbook/tests/edits/test_edits_comment.py b/cookbook/tests/edits/test_edits_comment.py deleted file mode 100644 index 0c8216f0..00000000 --- a/cookbook/tests/edits/test_edits_comment.py +++ /dev/null @@ -1,57 +0,0 @@ -from cookbook.models import Comment, Recipe -from cookbook.tests.views.test_views import TestViews -from django.contrib import auth -from django.urls import reverse - - -class TestEditsComment(TestViews): - - def setUp(self): - super(TestEditsComment, self).setUp() - - self.recipe = Recipe.objects.create( - internal=True, - working_time=1, - waiting_time=1, - created_by=auth.get_user(self.user_client_1) - ) - - self.comment = Comment.objects.create( - text='TestStorage', - created_by=auth.get_user(self.guest_client_1), - recipe=self.recipe - ) - self.url = reverse('edit_comment', args=[self.comment.pk]) - - def test_new_comment(self): - r = self.user_client_1.post( - reverse( - 'view_recipe', - args=[self.recipe.pk] - ), - { - 'comment-text': 'Test Comment Text', - 'comment-recipe': self.recipe.pk - } - ) - - self.assertEqual(r.status_code, 200) - - def test_edit_comment_permissions(self): - r = self.anonymous_client.get(self.url) - self.assertEqual(r.status_code, 302) - - r = self.guest_client_1.get(self.url) - self.assertEqual(r.status_code, 200) - - r = self.guest_client_2.get(self.url) - self.assertEqual(r.status_code, 302) - - r = self.user_client_1.get(self.url) - self.assertEqual(r.status_code, 302) - - r = self.admin_client_1.get(self.url) - self.assertEqual(r.status_code, 302) - - r = self.superuser_client.get(self.url) - self.assertEqual(r.status_code, 200) diff --git a/cookbook/tests/pytest/edits/test_edits_recipe.py b/cookbook/tests/edits/test_edits_recipe.py similarity index 95% rename from cookbook/tests/pytest/edits/test_edits_recipe.py rename to cookbook/tests/edits/test_edits_recipe.py index 894a8d5c..3cf8b380 100644 --- a/cookbook/tests/pytest/edits/test_edits_recipe.py +++ b/cookbook/tests/edits/test_edits_recipe.py @@ -1,5 +1,4 @@ -from cookbook.models import Food, Recipe, Storage, Unit -from cookbook.tests.views.test_views import TestViews +from cookbook.models import Recipe, Storage from django.contrib import auth from django.urls import reverse from pytest_django.asserts import assertTemplateUsed diff --git a/cookbook/tests/edits/test_edits_storage.py b/cookbook/tests/edits/test_edits_storage.py index cb122e71..125445e1 100644 --- a/cookbook/tests/edits/test_edits_storage.py +++ b/cookbook/tests/edits/test_edits_storage.py @@ -1,68 +1,58 @@ from cookbook.models import Storage -from cookbook.tests.views.test_views import TestViews from django.contrib import auth from django.urls import reverse +import pytest -class TestEditsRecipe(TestViews): +@pytest.fixture +def storage_obj(a1_s1, space_1): + return Storage.objects.create( + name='TestStorage', + method=Storage.DROPBOX, + created_by=auth.get_user(a1_s1), + token='test', + username='test', + password='test', + space=space_1, + ) - def setUp(self): - super(TestEditsRecipe, self).setUp() - self.storage = Storage.objects.create( - name='TestStorage', - method=Storage.DROPBOX, - created_by=auth.get_user(self.admin_client_1), - token='test', - username='test', - password='test', - ) - self.url = reverse('edit_storage', args=[self.storage.pk]) +def test_edit_storage(storage_obj, a1_s1, a1_s2): + r = a1_s1.post( + reverse('edit_storage', args={storage_obj.pk}), + { + 'name': 'NewStorage', + 'password': '1234_pw', + 'token': '1234_token', + 'method': Storage.DROPBOX + } + ) + storage_obj.refresh_from_db() + assert r.status_code == 200 + assert storage_obj.password == '1234_pw' + assert storage_obj.token == '1234_token' - def test_edit_storage(self): - r = self.admin_client_1.post( - self.url, - { - 'name': 'NewStorage', - 'password': '1234_pw', - 'token': '1234_token', - 'method': Storage.DROPBOX - } - ) - self.storage.refresh_from_db() - self.assertEqual(self.storage.password, '1234_pw') - self.assertEqual(self.storage.token, '1234_token') + r = a1_s2.post( + reverse('edit_storage', args={storage_obj.pk}), + { + 'name': 'NewStorage', + 'password': '1234_pw', + 'token': '1234_token', + 'method': Storage.DROPBOX + } + ) + assert r.status_code == 404 - r = self.admin_client_1.post( - self.url, - { - 'name': 'NewStorage', - 'password': '1234_pw', - 'token': '1234_token', - 'method': 'not_a_valid_method' - } - ) - self.assertFormError( - r, - 'form', - 'method', - [ - 'Select a valid choice. not_a_valid_method is not one of the available choices.' # noqa: E501 - ] - ) - def test_edit_storage_permissions(self): - r = self.anonymous_client.get(self.url) - self.assertEqual(r.status_code, 302) - - r = self.guest_client_1.get(self.url) - self.assertEqual(r.status_code, 302) - - r = self.user_client_1.get(self.url) - self.assertEqual(r.status_code, 302) - - r = self.admin_client_1.get(self.url) - self.assertEqual(r.status_code, 200) - - r = self.superuser_client.get(self.url) - self.assertEqual(r.status_code, 200) +@pytest.mark.parametrize("arg", [ + ['a_u', 302], + ['g1_s1', 302], + ['u1_s1', 302], + ['a1_s1', 200], + ['g1_s2', 302], + ['u1_s2', 302], + ['a1_s2', 404], +]) +def test_view_permission(arg, request, storage_obj): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('edit_storage', args={storage_obj.pk})).status_code == arg[1] diff --git a/cookbook/tests/pytest/api/__init__.py b/cookbook/tests/other/__init__.py similarity index 100% rename from cookbook/tests/pytest/api/__init__.py rename to cookbook/tests/other/__init__.py diff --git a/cookbook/tests/pytest/other/test_ingredient_parser.py b/cookbook/tests/other/test_ingredient_parser.py similarity index 100% rename from cookbook/tests/pytest/other/test_ingredient_parser.py rename to cookbook/tests/other/test_ingredient_parser.py diff --git a/cookbook/tests/other/test_url_import.py b/cookbook/tests/other/test_url_import.py new file mode 100644 index 00000000..9e11da08 --- /dev/null +++ b/cookbook/tests/other/test_url_import.py @@ -0,0 +1,28 @@ +import json + +from django_scopes import scopes_disabled + +from cookbook.helper.recipe_url_import import get_from_html + +# TODO this test is really bad, need to find a better solution, also pytest does not like those paths +# def test_ld_json(): +# with scopes_disabled(): +# test_list = [ +# {'file': 'resources/websites/ld_json_1.html', 'result_length': 3237}, +# {'file': 'resources/websites/ld_json_2.html', 'result_length': 1525}, +# {'file': 'resources/websites/ld_json_3.html', 'result_length': 1644}, +# {'file': 'resources/websites/ld_json_4.html', 'result_length': 1744}, +# {'file': 'resources/websites/ld_json_itemList.html', 'result_length': 3222}, +# {'file': 'resources/websites/ld_json_multiple.html', 'result_length': 1621}, +# {'file': 'resources/websites/micro_data_1.html', 'result_length': 1094}, +# {'file': 'resources/websites/micro_data_2.html', 'result_length': 1453}, +# {'file': 'resources/websites/micro_data_3.html', 'result_length': 1163}, +# {'file': 'resources/websites/micro_data_4.html', 'result_length': 4411}, +# ] +# +# for test in test_list: +# with open(test['file'], 'rb') as file: +# print(f'Testing {test["file"]} expecting length {test["result_length"]}') +# parsed_content = json.loads(get_from_html(file.read(), 'test_url', None).content) +# assert len(str(parsed_content)) == test['result_length'] +# file.close() diff --git a/cookbook/tests/pytest/edits/__init__.py b/cookbook/tests/pytest/edits/__init__.py deleted file mode 100644 index cd886345..00000000 --- a/cookbook/tests/pytest/edits/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.test import utils -from django_scopes import scopes_disabled - -# disables scoping error in all queries used inside the test FUNCTIONS -# FIXTURES need to have their own scopes_disabled!! -# This is done by hook pytest_fixture_setup in conftest.py for all non yield fixtures -utils.setup_databases = scopes_disabled()(utils.setup_databases) diff --git a/cookbook/tests/pytest/other/__init__.py b/cookbook/tests/pytest/other/__init__.py deleted file mode 100644 index cd886345..00000000 --- a/cookbook/tests/pytest/other/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.test import utils -from django_scopes import scopes_disabled - -# disables scoping error in all queries used inside the test FUNCTIONS -# FIXTURES need to have their own scopes_disabled!! -# This is done by hook pytest_fixture_setup in conftest.py for all non yield fixtures -utils.setup_databases = scopes_disabled()(utils.setup_databases) diff --git a/cookbook/tests/pytest/other/test_url_import.py b/cookbook/tests/pytest/other/test_url_import.py deleted file mode 100644 index a82d012f..00000000 --- a/cookbook/tests/pytest/other/test_url_import.py +++ /dev/null @@ -1,30 +0,0 @@ -import json - -from django_scopes import scopes_disabled - -from cookbook.helper.ingredient_parser import parse -from cookbook.helper.recipe_url_import import get_from_html -from cookbook.tests.test_setup import TestBase - - -def test_ld_json(): - with scopes_disabled(): - test_list = [ - {'file': '../resources/websites/ld_json_1.html', 'result_length': 3237}, - {'file': '../resources/websites/ld_json_2.html', 'result_length': 1525}, - {'file': '../resources/websites/ld_json_3.html', 'result_length': 1644}, - {'file': '../resources/websites/ld_json_4.html', 'result_length': 1744}, - {'file': '../resources/websites/ld_json_itemList.html', 'result_length': 3222}, - {'file': '../resources/websites/ld_json_multiple.html', 'result_length': 1621}, - {'file': '../resources/websites/micro_data_1.html', 'result_length': 1094}, - {'file': '../resources/websites/micro_data_2.html', 'result_length': 1453}, - {'file': '../resources/websites/micro_data_3.html', 'result_length': 1163}, - {'file': '../resources/websites/micro_data_4.html', 'result_length': 4411}, - ] - - for test in test_list: - with open(test['file'], 'rb') as file: - print(f'Testing {test["file"]} expecting length {test["result_length"]}') - parsed_content = json.loads(get_from_html(file.read(), 'test_url', None).content) - assert len(str(parsed_content)) == test['result_length'] - file.close() diff --git a/cookbook/tests/pytest/resources/image.jpg b/cookbook/tests/resources/image.jpg similarity index 100% rename from cookbook/tests/pytest/resources/image.jpg rename to cookbook/tests/resources/image.jpg diff --git a/cookbook/tests/pytest/resources/image.png b/cookbook/tests/resources/image.png similarity index 100% rename from cookbook/tests/pytest/resources/image.png rename to cookbook/tests/resources/image.png diff --git a/cookbook/tests/pytest/resources/websites/ld_json_1.html b/cookbook/tests/resources/websites/ld_json_1.html similarity index 100% rename from cookbook/tests/pytest/resources/websites/ld_json_1.html rename to cookbook/tests/resources/websites/ld_json_1.html diff --git a/cookbook/tests/pytest/resources/websites/ld_json_2.html b/cookbook/tests/resources/websites/ld_json_2.html similarity index 100% rename from cookbook/tests/pytest/resources/websites/ld_json_2.html rename to cookbook/tests/resources/websites/ld_json_2.html diff --git a/cookbook/tests/pytest/resources/websites/ld_json_3.html b/cookbook/tests/resources/websites/ld_json_3.html similarity index 100% rename from cookbook/tests/pytest/resources/websites/ld_json_3.html rename to cookbook/tests/resources/websites/ld_json_3.html diff --git a/cookbook/tests/pytest/resources/websites/ld_json_4.html b/cookbook/tests/resources/websites/ld_json_4.html similarity index 100% rename from cookbook/tests/pytest/resources/websites/ld_json_4.html rename to cookbook/tests/resources/websites/ld_json_4.html diff --git a/cookbook/tests/pytest/resources/websites/ld_json_itemList.html b/cookbook/tests/resources/websites/ld_json_itemList.html similarity index 100% rename from cookbook/tests/pytest/resources/websites/ld_json_itemList.html rename to cookbook/tests/resources/websites/ld_json_itemList.html diff --git a/cookbook/tests/pytest/resources/websites/ld_json_multiple.html b/cookbook/tests/resources/websites/ld_json_multiple.html similarity index 100% rename from cookbook/tests/pytest/resources/websites/ld_json_multiple.html rename to cookbook/tests/resources/websites/ld_json_multiple.html diff --git a/cookbook/tests/pytest/resources/websites/micro_data_1.html b/cookbook/tests/resources/websites/micro_data_1.html similarity index 100% rename from cookbook/tests/pytest/resources/websites/micro_data_1.html rename to cookbook/tests/resources/websites/micro_data_1.html diff --git a/cookbook/tests/pytest/resources/websites/micro_data_2.html b/cookbook/tests/resources/websites/micro_data_2.html similarity index 100% rename from cookbook/tests/pytest/resources/websites/micro_data_2.html rename to cookbook/tests/resources/websites/micro_data_2.html diff --git a/cookbook/tests/pytest/resources/websites/micro_data_3.html b/cookbook/tests/resources/websites/micro_data_3.html similarity index 100% rename from cookbook/tests/pytest/resources/websites/micro_data_3.html rename to cookbook/tests/resources/websites/micro_data_3.html diff --git a/cookbook/tests/pytest/resources/websites/micro_data_4.html b/cookbook/tests/resources/websites/micro_data_4.html similarity index 100% rename from cookbook/tests/pytest/resources/websites/micro_data_4.html rename to cookbook/tests/resources/websites/micro_data_4.html diff --git a/cookbook/tests/test_setup.py b/cookbook/tests/test_setup.py deleted file mode 100644 index a540b66a..00000000 --- a/cookbook/tests/test_setup.py +++ /dev/null @@ -1,70 +0,0 @@ -from django.contrib import auth -from django.contrib.auth.models import Group, User -from django.test import Client, TestCase - -from cookbook.models import Space - - -class TestBase(TestCase): - superuser_client = None - anonymous_client = None - - guest_client_1 = None - guest_client_2 = None - user_client_1 = None - user_client_2 = None - admin_client_1 = None - admin_client_2 = None - - s2_guest_client_1 = None - s2_user_client_1 = None - s2_admin_client_1 = None - s2_superuser_client = None - - def create_login_user(self, name, group, space, superuser=False): - client = Client() - setattr(self, name, client) - client.force_login(User.objects.get_or_create(username=name)[0]) - user = auth.get_user(getattr(self, name)) - user.groups.add(Group.objects.get(name=group)) - self.assertTrue(user.is_authenticated) - if superuser: - user.is_superuser = True - - user.userpreference.space = space - user.save() - return user - - def setUp(self): - # users for space 1 - space_1 = Space.objects.create(name='space 1') - - self.create_login_user('admin_client_1', 'admin', space_1) - self.create_login_user('admin_client_2', 'admin', space_1) - - self.create_login_user('user_client_1', 'user', space_1) - self.create_login_user('user_client_2', 'user', space_1) - - self.create_login_user('guest_client_1', 'guest', space_1) - self.create_login_user('guest_client_2', 'guest', space_1) - - self.anonymous_client = Client() - - self.create_login_user('superuser_client', 'admin', space_1, superuser=True) - - # users for space 2 - space_2 = Space.objects.create(name='space 2') - self.create_login_user('s2_admin_client_1', 'admin', space_2) - self.create_login_user('s2_user_client_1', 'user', space_2) - self.create_login_user('s2_guest_client_1', 'guest', space_2) - self.create_login_user('s2_superuser_client', 'admin', space_2, superuser=True) - - def batch_requests(self, clients, url, method='get', payload={}, content_type=''): - for c in clients: - if method == 'get': - r = c[0].get(url) - self.assertEqual( - r.status_code, - c[1], - msg=f'GET request failed for user {auth.get_user(c[0])} when testing url {url}' # noqa: E501 - ) diff --git a/cookbook/tests/views/__init__.py b/cookbook/tests/views/__init__.py index e69de29b..cd886345 100644 --- a/cookbook/tests/views/__init__.py +++ b/cookbook/tests/views/__init__.py @@ -0,0 +1,7 @@ +from django.test import utils +from django_scopes import scopes_disabled + +# disables scoping error in all queries used inside the test FUNCTIONS +# FIXTURES need to have their own scopes_disabled!! +# This is done by hook pytest_fixture_setup in conftest.py for all non yield fixtures +utils.setup_databases = scopes_disabled()(utils.setup_databases) diff --git a/cookbook/tests/views/test_views.py b/cookbook/tests/views/test_views.py deleted file mode 100644 index 91da6c98..00000000 --- a/cookbook/tests/views/test_views.py +++ /dev/null @@ -1,5 +0,0 @@ -from cookbook.tests.test_setup import TestBase - - -class TestViews(TestBase): - pass diff --git a/cookbook/tests/views/test_views_api.py b/cookbook/tests/views/test_views_api.py index f36987d1..a31da5d7 100644 --- a/cookbook/tests/views/test_views_api.py +++ b/cookbook/tests/views/test_views_api.py @@ -1,43 +1,34 @@ +import pytest + from cookbook.models import Recipe -from cookbook.tests.views.test_views import TestViews from django.contrib import auth from django.urls import reverse -class TestViewsApi(TestViews): +@pytest.mark.parametrize("arg", [ + ['a_u', 302], + ['g1_s1', 302], + ['u1_s1', 200], + ['a1_s1', 200], + ['g1_s2', 302], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_external_link_permission(arg, request, ext_recipe_1_s1): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('api_get_external_file_link', args=[ext_recipe_1_s1.pk])).status_code == arg[1] - def test_external_link_permission(self): - recipe = Recipe.objects.create( - internal=False, - link='test', - working_time=1, - waiting_time=1, - created_by=auth.get_user(self.user_client_1) - ) - url = reverse('api_get_external_file_link', args=[recipe.pk]) - self.assertEqual(self.anonymous_client.get(url).status_code, 302) - self.assertEqual(self.guest_client_1.get(url).status_code, 302) - self.assertEqual(self.user_client_1.get(url).status_code, 200) - self.assertEqual(self.admin_client_1.get(url).status_code, 200) - self.assertEqual(self.superuser_client.get(url).status_code, 200) +@pytest.mark.parametrize("arg", [ + ['a_u', 302], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], + ['g1_s2', 404], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_external_link_permission(arg, request, ext_recipe_1_s1): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('api_get_recipe_file', args=[ext_recipe_1_s1.pk])).status_code == arg[1] - def test_file_permission(self): - recipe = Recipe.objects.create( - internal=False, - link='test', - working_time=1, - waiting_time=1, - created_by=auth.get_user(self.user_client_1) - ) - - url = reverse('api_get_recipe_file', args=[recipe.pk]) - - self.assertEqual(self.anonymous_client.get(url).status_code, 302) - self.assertEqual(self.guest_client_1.get(url).status_code, 200) - - def test_sync_permission(self): - url = reverse('api_sync') - - self.assertEqual(self.anonymous_client.get(url).status_code, 302) - self.assertEqual(self.guest_client_1.get(url).status_code, 302) diff --git a/cookbook/tests/views/test_views_general.py b/cookbook/tests/views/test_views_general.py index 69675ff9..fd282edb 100644 --- a/cookbook/tests/views/test_views_general.py +++ b/cookbook/tests/views/test_views_general.py @@ -1,138 +1,121 @@ -from cookbook.tests.views.test_views import TestViews +import pytest from django.urls import reverse -class TestViewsGeneral(TestViews): +def test_index(): + # TODO add appropriate test + pass - def test_index(self): - # TODO add appropriate test - pass - def test_search(self): - # TODO add appropriate test - pass +def test_search(): + # TODO add appropriate test + pass - def test_view(self): - # TODO add appropriate test - pass - def test_books(self): - url = reverse('view_books') - self.batch_requests( - [ - (self.anonymous_client, 302), - (self.guest_client_1, 302), - (self.user_client_1, 200), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - url - ) +def test_view(): + # TODO add appropriate test + pass - def test_plan(self): - url = reverse('view_plan') - self.batch_requests( - [ - (self.anonymous_client, 302), - (self.guest_client_1, 302), - (self.user_client_1, 200), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - url - ) - def test_plan_entry(self): - # TODO add appropriate test - pass +@pytest.mark.parametrize("arg", [ + ['a_u', 302], + ['g1_s1', 302], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_books(arg, request, ext_recipe_1_s1): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('view_books')).status_code == arg[1] - def test_shopping(self): - url = reverse('view_shopping') - self.batch_requests( - [ - (self.anonymous_client, 302), - (self.guest_client_1, 302), - (self.user_client_1, 200), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - url - ) - def test_settings(self): - url = reverse('view_settings') - self.batch_requests( - [ - (self.anonymous_client, 302), - (self.guest_client_1, 200), - (self.user_client_1, 200), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - url - ) +@pytest.mark.parametrize("arg", [ + ['a_u', 302], + ['g1_s1', 302], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_plan(arg, request, ext_recipe_1_s1): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('view_plan')).status_code == arg[1] - def test_history(self): - url = reverse('view_history') - self.batch_requests( - [ - (self.anonymous_client, 302), - (self.guest_client_1, 200), - (self.user_client_1, 200), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - url - ) - def test_system(self): - url = reverse('view_system') - self.batch_requests( - [ - (self.anonymous_client, 302), - (self.guest_client_1, 302), - (self.user_client_1, 302), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - url - ) +def test_plan_entry(): + # TODO add appropriate test + pass - def test_setup(self): - url = reverse('view_setup') - self.batch_requests( - [ - (self.anonymous_client, 302), - (self.guest_client_1, 302), - (self.user_client_1, 302), - (self.admin_client_1, 302), - (self.superuser_client, 302) - ], - url - ) - def test_markdown_info(self): - url = reverse('docs_markdown') - self.batch_requests( - [ - (self.anonymous_client, 200), - (self.guest_client_1, 200), - (self.user_client_1, 200), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - url - ) +@pytest.mark.parametrize("arg", [ + ['a_u', 302], + ['g1_s1', 302], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_shopping(arg, request, ext_recipe_1_s1): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('view_shopping')).status_code == arg[1] - def test_api_info(self): - url = reverse('docs_api') - self.batch_requests( - [ - (self.anonymous_client, 302), - (self.guest_client_1, 200), - (self.user_client_1, 200), - (self.admin_client_1, 200), - (self.superuser_client, 200) - ], - url - ) + +@pytest.mark.parametrize("arg", [ + ['a_u', 302], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_settings(arg, request, ext_recipe_1_s1): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('view_settings')).status_code == arg[1] + + +@pytest.mark.parametrize("arg", [ + ['a_u', 302], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_history(arg, request, ext_recipe_1_s1): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('view_history')).status_code == arg[1] + + +@pytest.mark.parametrize("arg", [ + ['a_u', 302], + ['g1_s1', 302], + ['u1_s1', 302], + ['a1_s1', 200], +]) +def test_system(arg, request, ext_recipe_1_s1): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('view_system')).status_code == arg[1] + + +@pytest.mark.parametrize("arg", [ + ['a_u', 302], + ['g1_s1', 302], + ['u1_s1', 302], + ['a1_s1', 302], +]) +def test_setup(arg, request, ext_recipe_1_s1): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('view_setup')).status_code == arg[1] + + +@pytest.mark.parametrize("arg", [ + ['a_u', 200], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_markdown_doc(arg, request, ext_recipe_1_s1): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('docs_markdown')).status_code == arg[1] + + +@pytest.mark.parametrize("arg", [ + ['a_u', 302], + ['g1_s1', 200], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_api_info(arg, request, ext_recipe_1_s1): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse('docs_api')).status_code == arg[1] diff --git a/cookbook/tests/views/test_views_recipe_share.py b/cookbook/tests/views/test_views_recipe_share.py index 38b342dd..86ee680d 100644 --- a/cookbook/tests/views/test_views_recipe_share.py +++ b/cookbook/tests/views/test_views_recipe_share.py @@ -1,52 +1,45 @@ import uuid -from cookbook.helper.permission_helper import share_link_valid -from cookbook.models import Recipe, ShareLink -from cookbook.tests.views.test_views import TestViews -from django.contrib import auth from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.helper.permission_helper import share_link_valid +from cookbook.models import ShareLink -class TestViewsGeneral(TestViews): +def test_share(recipe_1_s1, u1_s1, a_u): + with scopes_disabled(): + url = reverse('view_recipe', kwargs={'pk': recipe_1_s1.pk}) + r = u1_s1.get(url) + assert r.status_code == 200 - def test_share(self): - internal_recipe = Recipe.objects.create( - name='Test', - internal=True, - created_by=auth.get_user(self.user_client_1) - ) + r = a_u.get(url) + assert r.status_code == 302 - url = reverse('view_recipe', kwargs={'pk': internal_recipe.pk}) - r = self.user_client_1.get(url) - self.assertEqual(r.status_code, 200) - - r = self.anonymous_client.get(url) - self.assertEqual(r.status_code, 302) - - url = reverse('new_share_link', kwargs={'pk': internal_recipe.pk}) - r = self.user_client_1.get(url) - self.assertEqual(r.status_code, 302) - share = ShareLink.objects.filter(recipe=internal_recipe).first() - self.assertIsNotNone(share) - self.assertTrue(share_link_valid(internal_recipe, share.uuid)) + url = reverse('new_share_link', kwargs={'pk': recipe_1_s1.pk}) + r = u1_s1.get(url) + assert r.status_code == 302 + share = ShareLink.objects.filter(recipe=recipe_1_s1).first() + assert share + assert share_link_valid(recipe_1_s1, share.uuid) url = reverse( 'view_recipe', - kwargs={'pk': internal_recipe.pk, 'share': share.uuid} + kwargs={'pk': recipe_1_s1.pk, 'share': share.uuid} ) - r = self.anonymous_client.get(url) - self.assertEqual(r.status_code, 200) + r = a_u.get(url) + assert r.status_code == 200 url = reverse( 'view_recipe', - kwargs={'pk': (internal_recipe.pk + 1), 'share': share.uuid} + kwargs={'pk': (recipe_1_s1.pk + 1), 'share': share.uuid} ) - r = self.anonymous_client.get(url) - self.assertEqual(r.status_code, 404) + r = a_u.get(url) + assert r.status_code == 404 url = reverse( 'view_recipe', - kwargs={'pk': internal_recipe.pk, 'share': uuid.uuid4()} + kwargs={'pk': recipe_1_s1.pk, 'share': uuid.uuid4()} ) - r = self.anonymous_client.get(url) - self.assertEqual(r.status_code, 302) + r = a_u.get(url) + assert r.status_code == 302 diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 9e5cd0ab..5718b2f0 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -13,7 +13,7 @@ from django.core.exceptions import FieldError, ValidationError from django.core.files import File from django.db.models import Q from django.http import FileResponse, HttpResponse, JsonResponse -from django.shortcuts import redirect +from django.shortcuts import redirect, get_object_or_404 from django.utils.translation import gettext as _ from icalendar import Calendar, Event from rest_framework import decorators, viewsets, status @@ -416,7 +416,7 @@ def update_recipe_links(recipe): @group_required('user') def get_external_file_link(request, recipe_id): - recipe = Recipe.objects.filter(space=request.user.userpreference.space).get(id=recipe_id) + recipe = get_object_or_404(Recipe, pk=recipe_id, space=request.space) if not recipe.link: update_recipe_links(recipe) @@ -425,7 +425,7 @@ def get_external_file_link(request, recipe_id): @group_required('guest') def get_recipe_file(request, recipe_id): - recipe = Recipe.objects.filter(space=request.user.userpreference.space).get(id=recipe_id) + recipe = get_object_or_404(Recipe, pk=recipe_id, space=request.space) if recipe.storage: return FileResponse(get_recipe_provider(recipe).get_file(recipe)) else: From 2149f4034bf518687c600ec73889e89efb69b8bd Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 23:28:28 +0100 Subject: [PATCH 75/96] several shopping list improvements --- cookbook/models.py | 6 +++--- cookbook/templates/shopping_list.html | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/cookbook/models.py b/cookbook/models.py index c99cb691..2e9237c9 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -510,14 +510,14 @@ class ShoppingListRecipe(models.Model, PermissionModelMixin): recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, null=True, blank=True) servings = models.DecimalField(default=1, max_digits=8, decimal_places=4) - objects = ScopedManager(space='shoppinglist__space') + objects = ScopedManager(space='recipe__space') @staticmethod def get_space_key(): - return 'shoppinglist', 'space' + return 'recipe', 'space' def get_space(self): - return self.shoppinglist_set.first().space + return self.recipe.space def __str__(self): return f'Shopping list recipe {self.id} - {self.recipe}' diff --git a/cookbook/templates/shopping_list.html b/cookbook/templates/shopping_list.html index c52414d0..c366a2db 100644 --- a/cookbook/templates/shopping_list.html +++ b/cookbook/templates/shopping_list.html @@ -122,8 +122,8 @@ - + @change="dragChanged(c, $event)" handle=".handle"> + [[element.amount]] [[element.unit.name]] @@ -154,7 +154,7 @@
-
@@ -349,6 +349,8 @@
+
+
@@ -448,7 +450,7 @@ name: gettext('Uncategorized'), id: -1, entries: [], - order: 99999999 + order: -1 } } From 9280540927834ac92b8ce3dac4b99e3637fb6faa Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 23:48:49 +0100 Subject: [PATCH 76/96] updated ci command --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b9949b8..a113ead1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,4 +25,4 @@ jobs: python3 manage.py collectstatic_js_reverse - name: Django Testing project run: | - python3 manage.py test + pytest From d2a4a9d953308ca8acb19b93d915fa6212da65d8 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 23:50:37 +0100 Subject: [PATCH 77/96] addded pytest as dependency --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f95c9893..c83b2a55 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,4 +30,5 @@ Jinja2==2.11.3 django-webpack-loader==0.7.0 django-js-reverse==0.9.1 django-allauth==0.44.0 -django-scopes==1.2.0 \ No newline at end of file +django-scopes==1.2.0 +pytest==6.2.2 \ No newline at end of file From 77cfcb46027678d031a3bb115c7384b39df7059c Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Wed, 17 Mar 2021 23:52:41 +0100 Subject: [PATCH 78/96] and pytest django --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index c83b2a55..65f1071a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,4 +31,5 @@ django-webpack-loader==0.7.0 django-js-reverse==0.9.1 django-allauth==0.44.0 django-scopes==1.2.0 -pytest==6.2.2 \ No newline at end of file +pytest==6.2.2 +pytest-django==4.1.0 \ No newline at end of file From cb78f75f193a12cbaedeeaaac40baa06599a6953 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 10:56:12 +0100 Subject: [PATCH 79/96] fixed shopping list auto sync flickering --- cookbook/templates/shopping_list.html | 38 ++++++++++++++++++--------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/cookbook/templates/shopping_list.html b/cookbook/templates/shopping_list.html index c366a2db..bc816ca8 100644 --- a/cookbook/templates/shopping_list.html +++ b/cookbook/templates/shopping_list.html @@ -123,7 +123,8 @@ - + [[element.amount]] [[element.unit.name]] @@ -154,7 +155,8 @@
-
@@ -420,6 +422,8 @@ users_loading: false, onLine: navigator.onLine, simple_entry: '', + auto_sync_blocked: false, + auto_sync_running: false, entry_mode_simple: $cookies.isKey('shopping_entry_mode_simple') ? ($cookies.get('shopping_entry_mode_simple') === 'true') : true, }, directives: { @@ -559,7 +563,8 @@ {% if request.user.userpreference.shopping_auto_sync > 0 %} setInterval(() => { - if ((this.shopping_list_id !== null) && !this.edit_mode && window.navigator.onLine) { + if ((this.shopping_list_id !== null) && !this.edit_mode && window.navigator.onLine && !this.auto_sync_blocked && !this.auto_sync_running) { + this.auto_sync_running = true this.loadShoppingList(true) } }, {% widthratio request.user.userpreference.shopping_auto_sync 1 1000 %}) @@ -624,16 +629,19 @@ this.shopping_list = response.body this.loading = false } else { - let check_map = {} - for (let e of response.body.entries) { - check_map[e.id] = {checked: e.checked} - } + if (!this.auto_sync_blocked) { + let check_map = {} + for (let e of response.body.entries) { + check_map[e.id] = {checked: e.checked} + } - for (let se of this.shopping_list.entries) { - if (check_map[se.id] !== undefined) { - se.checked = check_map[se.id].checked + for (let se of this.shopping_list.entries) { + if (check_map[se.id] !== undefined) { + se.checked = check_map[se.id].checked + } } } + this.auto_sync_running = false } if (this.shopping_list.entries.length === 0) { this.edit_mode = true @@ -747,18 +755,24 @@ } }, entryChecked: function (entry) { + this.auto_sync_blocked = true + let updates = [] this.shopping_list.entries.forEach((item) => { if (entry.entries.includes(item.id)) { item.checked = entry.checked - this.$http.put("{% url 'api:shoppinglistentry-detail' 123456 %}".replace('123456', item.id), item, {}).then((response) => { + updates.push(this.$http.put("{% url 'api:shoppinglistentry-detail' 123456 %}".replace('123456', item.id), item, {}).then((response) => { }).catch((err) => { console.log(err) this.makeToast(gettext('Error'), gettext('There was an error updating a resource!') + err.bodyText, 'danger') this.loading = false - }) + })) } }) + + Promise.allSettled(updates).then(() => { + this.auto_sync_blocked = false + }) }, addEntry: function () { if (this.new_entry.food !== undefined) { From 6a25428b3c168af87b160dafc69bbbc086ecbd42 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 11:04:55 +0100 Subject: [PATCH 80/96] fixed shopping list share permission --- cookbook/helper/permission_helper.py | 2 +- cookbook/models.py | 8 ++++++++ cookbook/views/api.py | 8 ++++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/cookbook/helper/permission_helper.py b/cookbook/helper/permission_helper.py index e170063f..794107f1 100644 --- a/cookbook/helper/permission_helper.py +++ b/cookbook/helper/permission_helper.py @@ -79,7 +79,7 @@ def is_object_shared(user, obj): # share checks for relevant objects if not user.is_authenticated: return False - return user in obj.shared.all() + return user in obj.get_shared() def share_link_valid(recipe, share): diff --git a/cookbook/models.py b/cookbook/models.py index 2e9237c9..20bd0f75 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -45,6 +45,11 @@ class PermissionModelMixin: return self.user return None + def get_shared(self): + if getattr(self, 'shared', None): + return self.shared.all() + return [] + def get_space(self): p = '.'.join(self.get_space_key()) if getattr(self, p, None): @@ -549,6 +554,9 @@ class ShoppingListEntry(models.Model, PermissionModelMixin): def __str__(self): return f'Shopping list entry {self.id}' + def get_shared(self): + return self.shoppinglist_set.first().shared.all() + def get_owner(self): try: return self.shoppinglist_set.first().created_by diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 5718b2f0..862e60aa 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -337,19 +337,19 @@ class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin): class ShoppingListRecipeViewSet(viewsets.ModelViewSet): queryset = ShoppingListRecipe.objects serializer_class = ShoppingListRecipeSerializer - permission_classes = [CustomIsOwner, ] + permission_classes = [CustomIsOwner| CustomIsShared ] def get_queryset(self): - return self.queryset.filter(shoppinglist__created_by=self.request.user, shoppinglist__space=self.request.space).all() + return self.queryset.filter(Q(shoppinglist__created_by=self.request.user) | Q(shoppinglist__shared=self.request.user)).filter(shoppinglist__space=self.request.space).all() class ShoppingListEntryViewSet(viewsets.ModelViewSet): queryset = ShoppingListEntry.objects serializer_class = ShoppingListEntrySerializer - permission_classes = [CustomIsOwner, ] + permission_classes = [CustomIsOwner | CustomIsShared] def get_queryset(self): - return self.queryset.filter(shoppinglist__created_by=self.request.user, shoppinglist__space=self.request.space).all() + return self.queryset.filter(Q(shoppinglist__created_by=self.request.user) | Q(shoppinglist__shared=self.request.user)).filter(shoppinglist__space=self.request.space).all() class ShoppingListViewSet(viewsets.ModelViewSet): From 2e625715ccb1d6d6fa55dd7282ac5596ee5c30d2 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 11:14:34 +0100 Subject: [PATCH 81/96] updated help request template --- .github/ISSUE_TEMPLATE/help-request.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/help-request.md b/.github/ISSUE_TEMPLATE/help-request.md index aedd42cf..a8718edc 100644 --- a/.github/ISSUE_TEMPLATE/help-request.md +++ b/.github/ISSUE_TEMPLATE/help-request.md @@ -6,14 +6,16 @@ labels: setup issue assignees: '' --- - -### Version -Please provide your current version (can be found on the system page since v0.8.4) -Version: - -### Issue +## Issue Please describe your problem here + +## Setup Info +Version: (can be found on the system page since v0.8.4) +OS: e.g. Ubuntu 20.02 + +Other relevant information regarding your problem (proxies, firewalls, etc.) + ### `.env` Please include your `.env` config file (**make sure to remove/replace all secrets**) ``` @@ -25,3 +27,7 @@ When running with docker compose please provide your `docker-compose.yml` ``` docker-compose.yml content ``` + +### Logs +If you feel like there is anything interesting please post the output of `docker-compose logs` at +container startup and when the issue happens. \ No newline at end of file From daf0be37fd5298dbdf51ad71d51a37a8dda0ae83 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 11:18:09 +0100 Subject: [PATCH 82/96] upgraded javascritp dependencies --- cookbook/static/vue/css/chunk-vendors.css | 2 +- cookbook/static/vue/js/chunk-vendors.js | 22 +- cookbook/static/vue/js/offline_view.js | 2 +- cookbook/templates/sw.js | 2 +- vue/package.json | 4 +- vue/yarn.lock | 5569 +++++++++++---------- 6 files changed, 2873 insertions(+), 2728 deletions(-) diff --git a/cookbook/static/vue/css/chunk-vendors.css b/cookbook/static/vue/css/chunk-vendors.css index f3620b52..aafd58d7 100644 --- a/cookbook/static/vue/css/chunk-vendors.css +++ b/cookbook/static/vue/css/chunk-vendors.css @@ -1,4 +1,4 @@ @charset "UTF-8"; /*! * BootstrapVue Custom CSS (https://bootstrap-vue.org) - */.bv-no-focus-ring:focus{outline:none}@media (max-width:575.98px){.bv-d-xs-down-none{display:none!important}}@media (max-width:767.98px){.bv-d-sm-down-none{display:none!important}}@media (max-width:991.98px){.bv-d-md-down-none{display:none!important}}@media (max-width:1199.98px){.bv-d-lg-down-none{display:none!important}}.bv-d-xl-down-none{display:none!important}.form-control.focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control.focus.is-valid{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-control.focus.is-invalid{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.b-avatar{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;flex-shrink:0;width:2.5rem;height:2.5rem;font-size:inherit;font-weight:400;line-height:1;max-width:100%;max-height:auto;text-align:center;overflow:visible;position:relative;transition:color .15s ease-in-out,background-color .15s ease-in-out,box-shadow .15s ease-in-out}.b-avatar:focus{outline:0}.b-avatar.btn,.b-avatar[href]{padding:0;border:0}.b-avatar.btn .b-avatar-img img,.b-avatar[href] .b-avatar-img img{transition:transform .15s ease-in-out}.b-avatar.btn:not(:disabled):not(.disabled),.b-avatar[href]:not(:disabled):not(.disabled){cursor:pointer}.b-avatar.btn:not(:disabled):not(.disabled):hover .b-avatar-img img,.b-avatar[href]:not(:disabled):not(.disabled):hover .b-avatar-img img{transform:scale(1.15)}.b-avatar.disabled,.b-avatar:disabled,.b-avatar[disabled]{opacity:.65;pointer-events:none}.b-avatar .b-avatar-custom,.b-avatar .b-avatar-img,.b-avatar .b-avatar-text{border-radius:inherit;width:100%;height:100%;overflow:hidden;display:flex;justify-content:center;align-items:center;-webkit-mask-image:radial-gradient(#fff,#000);mask-image:radial-gradient(#fff,#000)}.b-avatar .b-avatar-text{text-transform:uppercase;white-space:nowrap}.b-avatar[href]{text-decoration:none}.b-avatar>.b-icon{width:60%;height:auto;max-width:100%}.b-avatar .b-avatar-img img{width:100%;height:100%;max-height:auto;border-radius:inherit;-o-object-fit:cover;object-fit:cover}.b-avatar .b-avatar-badge{position:absolute;min-height:1.5em;min-width:1.5em;padding:.25em;line-height:1;border-radius:10em;font-size:70%;font-weight:700;z-index:1}.b-avatar-sm{width:1.5rem;height:1.5rem}.b-avatar-sm .b-avatar-text{font-size:.6rem}.b-avatar-sm .b-avatar-badge{font-size:.42rem}.b-avatar-lg{width:3.5rem;height:3.5rem}.b-avatar-lg .b-avatar-text{font-size:1.4rem}.b-avatar-lg .b-avatar-badge{font-size:.98rem}.b-avatar-group .b-avatar-group-inner{display:flex;flex-wrap:wrap}.b-avatar-group .b-avatar{border:1px solid #dee2e6}.b-avatar-group .btn.b-avatar:hover:not(.disabled):not(disabled),.b-avatar-group a.b-avatar:hover:not(.disabled):not(disabled){z-index:1}.b-calendar{display:inline-flex}.b-calendar .b-calendar-inner{min-width:250px}.b-calendar .b-calendar-header,.b-calendar .b-calendar-nav{margin-bottom:.25rem}.b-calendar .b-calendar-nav .btn{padding:.25rem}.b-calendar output{padding:.25rem;font-size:80%}.b-calendar output.readonly{background-color:#e9ecef;opacity:1}.b-calendar .b-calendar-footer{margin-top:.5rem}.b-calendar .b-calendar-grid{padding:0;margin:0;overflow:hidden}.b-calendar .b-calendar-grid .row{flex-wrap:nowrap}.b-calendar .b-calendar-grid-caption{padding:.25rem}.b-calendar .b-calendar-grid-body .col[data-date] .btn{width:32px;height:32px;font-size:14px;line-height:1;margin:3px auto;padding:9px 0}.b-calendar .btn.disabled,.b-calendar .btn:disabled,.b-calendar .btn[aria-disabled=true]{cursor:default;pointer-events:none}.card-img-left{border-top-left-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-img-right{border-top-right-radius:calc(.25rem - 1px);border-bottom-right-radius:calc(.25rem - 1px)}.dropdown.dropleft .dropdown-toggle.dropdown-toggle-no-caret:before,.dropdown:not(.dropleft) .dropdown-toggle.dropdown-toggle-no-caret:after{display:none!important}.dropdown .dropdown-menu:focus{outline:none}.b-dropdown-form{display:inline-block;padding:.25rem 1.5rem;width:100%;clear:both;font-weight:400}.b-dropdown-form:focus{outline:1px dotted!important;outline:5px auto -webkit-focus-ring-color!important}.b-dropdown-form.disabled,.b-dropdown-form:disabled{outline:0!important;color:#6c757d;pointer-events:none}.b-dropdown-text{display:inline-block;padding:.25rem 1.5rem;margin-bottom:0;width:100%;clear:both;font-weight:lighter}.custom-checkbox.b-custom-control-lg,.input-group-lg .custom-checkbox{font-size:1.25rem;line-height:1.5;padding-left:1.875rem}.custom-checkbox.b-custom-control-lg .custom-control-label:before,.input-group-lg .custom-checkbox .custom-control-label:before{top:.3125rem;left:-1.875rem;width:1.25rem;height:1.25rem;border-radius:.3rem}.custom-checkbox.b-custom-control-lg .custom-control-label:after,.input-group-lg .custom-checkbox .custom-control-label:after{top:.3125rem;left:-1.875rem;width:1.25rem;height:1.25rem;background-size:50% 50%}.custom-checkbox.b-custom-control-sm,.input-group-sm .custom-checkbox{font-size:.875rem;line-height:1.5;padding-left:1.3125rem}.custom-checkbox.b-custom-control-sm .custom-control-label:before,.input-group-sm .custom-checkbox .custom-control-label:before{top:.21875rem;left:-1.3125rem;width:.875rem;height:.875rem;border-radius:.2rem}.custom-checkbox.b-custom-control-sm .custom-control-label:after,.input-group-sm .custom-checkbox .custom-control-label:after{top:.21875rem;left:-1.3125rem;width:.875rem;height:.875rem;background-size:50% 50%}.custom-switch.b-custom-control-lg,.input-group-lg .custom-switch{padding-left:2.8125rem}.custom-switch.b-custom-control-lg .custom-control-label,.input-group-lg .custom-switch .custom-control-label{font-size:1.25rem;line-height:1.5}.custom-switch.b-custom-control-lg .custom-control-label:before,.input-group-lg .custom-switch .custom-control-label:before{top:.3125rem;height:1.25rem;left:-2.8125rem;width:2.1875rem;border-radius:.625rem}.custom-switch.b-custom-control-lg .custom-control-label:after,.input-group-lg .custom-switch .custom-control-label:after{top:calc(.3125rem + 2px);left:calc(-2.8125rem + 2px);width:calc(1.25rem - 4px);height:calc(1.25rem - 4px);border-radius:.625rem;background-size:50% 50%}.custom-switch.b-custom-control-lg .custom-control-input:checked~.custom-control-label:after,.input-group-lg .custom-switch .custom-control-input:checked~.custom-control-label:after{transform:translateX(.9375rem)}.custom-switch.b-custom-control-sm,.input-group-sm .custom-switch{padding-left:1.96875rem}.custom-switch.b-custom-control-sm .custom-control-label,.input-group-sm .custom-switch .custom-control-label{font-size:.875rem;line-height:1.5}.custom-switch.b-custom-control-sm .custom-control-label:before,.input-group-sm .custom-switch .custom-control-label:before{top:.21875rem;left:-1.96875rem;width:1.53125rem;height:.875rem;border-radius:.4375rem}.custom-switch.b-custom-control-sm .custom-control-label:after,.input-group-sm .custom-switch .custom-control-label:after{top:calc(.21875rem + 2px);left:calc(-1.96875rem + 2px);width:calc(.875rem - 4px);height:calc(.875rem - 4px);border-radius:.4375rem;background-size:50% 50%}.custom-switch.b-custom-control-sm .custom-control-input:checked~.custom-control-label:after,.input-group-sm .custom-switch .custom-control-input:checked~.custom-control-label:after{transform:translateX(.65625rem)}.input-group>.input-group-append:last-child>.btn-group:not(:last-child):not(.dropdown-toggle)>.btn,.input-group>.input-group-append:not(:last-child)>.btn-group>.btn,.input-group>.input-group-prepend>.btn-group>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn-group>.btn,.input-group>.input-group-prepend:first-child>.btn-group:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.btn-group>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.b-form-btn-label-control.form-control{display:flex;align-items:stretch;height:auto;padding:0;background-image:none}.input-group .b-form-btn-label-control.form-control{padding:0}.b-form-btn-label-control.form-control[dir=rtl],[dir=rtl] .b-form-btn-label-control.form-control{flex-direction:row-reverse}.b-form-btn-label-control.form-control[dir=rtl]>label,[dir=rtl] .b-form-btn-label-control.form-control>label{text-align:right}.b-form-btn-label-control.form-control>.btn{line-height:1;font-size:inherit;box-shadow:none!important;border:0}.b-form-btn-label-control.form-control>.btn:disabled{pointer-events:none}.b-form-btn-label-control.form-control.is-valid>.btn{color:#28a745}.b-form-btn-label-control.form-control.is-invalid>.btn{color:#dc3545}.b-form-btn-label-control.form-control>.dropdown-menu{padding:.5rem}.b-form-btn-label-control.form-control>.form-control{height:auto;min-height:calc(1.5em + .75rem);padding-left:.25rem;margin:0;border:0;outline:0;background:transparent;word-break:break-word;font-size:inherit;white-space:normal;cursor:pointer}.b-form-btn-label-control.form-control>.form-control.form-control-sm{min-height:calc(1.5em + .5rem)}.b-form-btn-label-control.form-control>.form-control.form-control-lg{min-height:calc(1.5em + 1rem)}.input-group.input-group-sm .b-form-btn-label-control.form-control>.form-control{min-height:calc(1.5em + .5rem);padding-top:.25rem;padding-bottom:.25rem}.input-group.input-group-lg .b-form-btn-label-control.form-control>.form-control{min-height:calc(1.5em + 1rem);padding-top:.5rem;padding-bottom:.5rem}.b-form-btn-label-control.form-control[aria-disabled=true],.b-form-btn-label-control.form-control[aria-readonly=true]{background-color:#e9ecef;opacity:1}.b-form-btn-label-control.form-control[aria-disabled=true]{pointer-events:none}.b-form-btn-label-control.form-control[aria-disabled=true]>label{cursor:default}.b-form-btn-label-control.btn-group>.dropdown-menu{padding:.5rem}.custom-file-label{white-space:nowrap;overflow-x:hidden}.b-custom-control-lg.custom-file,.b-custom-control-lg .custom-file-input,.b-custom-control-lg .custom-file-label,.input-group-lg.custom-file,.input-group-lg .custom-file-input,.input-group-lg .custom-file-label{font-size:1.25rem;height:calc(1.5em + 1rem + 2px)}.b-custom-control-lg .custom-file-label,.b-custom-control-lg .custom-file-label:after,.input-group-lg .custom-file-label,.input-group-lg .custom-file-label:after{padding:.5rem 1rem;line-height:1.5}.b-custom-control-lg .custom-file-label,.input-group-lg .custom-file-label{border-radius:.3rem}.b-custom-control-lg .custom-file-label:after,.input-group-lg .custom-file-label:after{font-size:inherit;height:calc(1.5em + 1rem);border-radius:0 .3rem .3rem 0}.b-custom-control-sm.custom-file,.b-custom-control-sm .custom-file-input,.b-custom-control-sm .custom-file-label,.input-group-sm.custom-file,.input-group-sm .custom-file-input,.input-group-sm .custom-file-label{font-size:.875rem;height:calc(1.5em + .5rem + 2px)}.b-custom-control-sm .custom-file-label,.b-custom-control-sm .custom-file-label:after,.input-group-sm .custom-file-label,.input-group-sm .custom-file-label:after{padding:.25rem .5rem;line-height:1.5}.b-custom-control-sm .custom-file-label,.input-group-sm .custom-file-label{border-radius:.2rem}.b-custom-control-sm .custom-file-label:after,.input-group-sm .custom-file-label:after{font-size:inherit;height:calc(1.5em + .5rem);border-radius:0 .2rem .2rem 0}.form-control.is-invalid,.form-control.is-valid,.was-validated .form-control:invalid,.was-validated .form-control:valid{background-position:right calc(.375em + .1875rem) center}input[type=color].form-control{height:calc(1.5em + .75rem + 2px);padding:.125rem .25rem}.input-group-sm input[type=color].form-control,input[type=color].form-control.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.125rem .25rem}.input-group-lg input[type=color].form-control,input[type=color].form-control.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.125rem .25rem}input[type=color].form-control:disabled{background-color:#adb5bd;opacity:.65}.input-group>.custom-range{position:relative;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.custom-file+.custom-range,.input-group>.custom-range+.custom-file,.input-group>.custom-range+.custom-range,.input-group>.custom-range+.custom-select,.input-group>.custom-range+.form-control,.input-group>.custom-range+.form-control-plaintext,.input-group>.custom-select+.custom-range,.input-group>.form-control+.custom-range,.input-group>.form-control-plaintext+.custom-range{margin-left:-1px}.input-group>.custom-range:focus{z-index:3}.input-group>.custom-range:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-range:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-range{padding:0 .75rem;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;height:calc(1.5em + .75rem + 2px);border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.input-group>.custom-range{transition:none}}.input-group>.custom-range:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.input-group>.custom-range:disabled,.input-group>.custom-range[readonly]{background-color:#e9ecef}.input-group-lg>.custom-range{height:calc(1.5em + 1rem + 2px);padding:0 1rem;border-radius:.3rem}.input-group-sm>.custom-range{height:calc(1.5em + .5rem + 2px);padding:0 .5rem;border-radius:.2rem}.input-group .custom-range.is-valid,.was-validated .input-group .custom-range:valid{border-color:#28a745}.input-group .custom-range.is-valid:focus,.was-validated .input-group .custom-range:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-range.is-valid:focus::-webkit-slider-thumb,.was-validated .custom-range:valid:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #9be7ac}.custom-range.is-valid:focus::-moz-range-thumb,.was-validated .custom-range:valid:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #9be7ac}.custom-range.is-valid:focus::-ms-thumb,.was-validated .custom-range:valid:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #9be7ac}.custom-range.is-valid::-webkit-slider-thumb,.was-validated .custom-range:valid::-webkit-slider-thumb{background-color:#28a745;background-image:none}.custom-range.is-valid::-webkit-slider-thumb:active,.was-validated .custom-range:valid::-webkit-slider-thumb:active{background-color:#9be7ac;background-image:none}.custom-range.is-valid::-webkit-slider-runnable-track,.was-validated .custom-range:valid::-webkit-slider-runnable-track{background-color:rgba(40,167,69,.35)}.custom-range.is-valid::-moz-range-thumb,.was-validated .custom-range:valid::-moz-range-thumb{background-color:#28a745;background-image:none}.custom-range.is-valid::-moz-range-thumb:active,.was-validated .custom-range:valid::-moz-range-thumb:active{background-color:#9be7ac;background-image:none}.custom-range.is-valid::-moz-range-track,.was-validated .custom-range:valid::-moz-range-track{background:rgba(40,167,69,.35)}.custom-range.is-valid~.valid-feedback,.custom-range.is-valid~.valid-tooltip,.was-validated .custom-range:valid~.valid-feedback,.was-validated .custom-range:valid~.valid-tooltip{display:block}.custom-range.is-valid::-ms-thumb,.was-validated .custom-range:valid::-ms-thumb{background-color:#28a745;background-image:none}.custom-range.is-valid::-ms-thumb:active,.was-validated .custom-range:valid::-ms-thumb:active{background-color:#9be7ac;background-image:none}.custom-range.is-valid::-ms-track-lower,.custom-range.is-valid::-ms-track-upper,.was-validated .custom-range:valid::-ms-track-lower,.was-validated .custom-range:valid::-ms-track-upper{background:rgba(40,167,69,.35)}.input-group .custom-range.is-invalid,.was-validated .input-group .custom-range:invalid{border-color:#dc3545}.input-group .custom-range.is-invalid:focus,.was-validated .input-group .custom-range:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-range.is-invalid:focus::-webkit-slider-thumb,.was-validated .custom-range:invalid:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #f6cdd1}.custom-range.is-invalid:focus::-moz-range-thumb,.was-validated .custom-range:invalid:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #f6cdd1}.custom-range.is-invalid:focus::-ms-thumb,.was-validated .custom-range:invalid:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #f6cdd1}.custom-range.is-invalid::-webkit-slider-thumb,.was-validated .custom-range:invalid::-webkit-slider-thumb{background-color:#dc3545;background-image:none}.custom-range.is-invalid::-webkit-slider-thumb:active,.was-validated .custom-range:invalid::-webkit-slider-thumb:active{background-color:#f6cdd1;background-image:none}.custom-range.is-invalid::-webkit-slider-runnable-track,.was-validated .custom-range:invalid::-webkit-slider-runnable-track{background-color:rgba(220,53,69,.35)}.custom-range.is-invalid::-moz-range-thumb,.was-validated .custom-range:invalid::-moz-range-thumb{background-color:#dc3545;background-image:none}.custom-range.is-invalid::-moz-range-thumb:active,.was-validated .custom-range:invalid::-moz-range-thumb:active{background-color:#f6cdd1;background-image:none}.custom-range.is-invalid::-moz-range-track,.was-validated .custom-range:invalid::-moz-range-track{background:rgba(220,53,69,.35)}.custom-range.is-invalid~.invalid-feedback,.custom-range.is-invalid~.invalid-tooltip,.was-validated .custom-range:invalid~.invalid-feedback,.was-validated .custom-range:invalid~.invalid-tooltip{display:block}.custom-range.is-invalid::-ms-thumb,.was-validated .custom-range:invalid::-ms-thumb{background-color:#dc3545;background-image:none}.custom-range.is-invalid::-ms-thumb:active,.was-validated .custom-range:invalid::-ms-thumb:active{background-color:#f6cdd1;background-image:none}.custom-range.is-invalid::-ms-track-lower,.custom-range.is-invalid::-ms-track-upper,.was-validated .custom-range:invalid::-ms-track-lower,.was-validated .custom-range:invalid::-ms-track-upper{background:rgba(220,53,69,.35)}.custom-radio.b-custom-control-lg,.input-group-lg .custom-radio{font-size:1.25rem;line-height:1.5;padding-left:1.875rem}.custom-radio.b-custom-control-lg .custom-control-label:before,.input-group-lg .custom-radio .custom-control-label:before{top:.3125rem;left:-1.875rem;width:1.25rem;height:1.25rem;border-radius:50%}.custom-radio.b-custom-control-lg .custom-control-label:after,.input-group-lg .custom-radio .custom-control-label:after{top:.3125rem;left:-1.875rem;width:1.25rem;height:1.25rem;background:no-repeat 50%/50% 50%}.custom-radio.b-custom-control-sm,.input-group-sm .custom-radio{font-size:.875rem;line-height:1.5;padding-left:1.3125rem}.custom-radio.b-custom-control-sm .custom-control-label:before,.input-group-sm .custom-radio .custom-control-label:before{top:.21875rem;left:-1.3125rem;width:.875rem;height:.875rem;border-radius:50%}.custom-radio.b-custom-control-sm .custom-control-label:after,.input-group-sm .custom-radio .custom-control-label:after{top:.21875rem;left:-1.3125rem;width:.875rem;height:.875rem;background:no-repeat 50%/50% 50%}.b-rating{text-align:center}.b-rating.d-inline-flex{width:auto}.b-rating .b-rating-star,.b-rating .b-rating-value{padding:0 .25em}.b-rating .b-rating-value{min-width:2.5em}.b-rating .b-rating-star{display:inline-flex;justify-content:center;outline:0}.b-rating .b-rating-star .b-rating-icon{display:inline-flex;transition:all .15s ease-in-out}.b-rating.disabled,.b-rating:disabled{background-color:#e9ecef;color:#6c757d}.b-rating:not(.disabled):not(.readonly) .b-rating-star{cursor:pointer}.b-rating:not(.disabled):not(.readonly) .b-rating-star:hover .b-rating-icon,.b-rating:not(.disabled):not(.readonly):focus:not(:hover) .b-rating-star.focused .b-rating-icon{transform:scale(1.5)}.b-rating[dir=rtl] .b-rating-star-half{transform:scaleX(-1)}.b-form-spinbutton{text-align:center;overflow:hidden;background-image:none;padding:0}.b-form-spinbutton[dir=rtl]:not(.flex-column),[dir=rtl] .b-form-spinbutton:not(.flex-column){flex-direction:row-reverse}.b-form-spinbutton output{font-size:inherit;outline:0;border:0;background-color:transparent;width:auto;margin:0;padding:0 .25rem}.b-form-spinbutton output>bdi,.b-form-spinbutton output>div{display:block;min-width:2.25em;height:1.5em}.b-form-spinbutton.flex-column{height:auto;width:auto}.b-form-spinbutton.flex-column output{margin:0 .25rem;padding:.25rem 0}.b-form-spinbutton:not(.d-inline-flex):not(.flex-column){output-width:100%}.b-form-spinbutton.d-inline-flex:not(.flex-column){width:auto}.b-form-spinbutton .btn{line-height:1;box-shadow:none!important}.b-form-spinbutton .btn:disabled{pointer-events:none}.b-form-spinbutton .btn:hover:not(:disabled)>div>.b-icon{transform:scale(1.25)}.b-form-spinbutton.disabled,.b-form-spinbutton.readonly{background-color:#e9ecef}.b-form-spinbutton.disabled{pointer-events:none}.b-form-tags .b-form-tags-list{margin-top:-.25rem}.b-form-tags .b-form-tags-list .b-form-tag,.b-form-tags .b-form-tags-list .b-from-tags-field{margin-top:.25rem}.b-form-tags.focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.b-form-tags.focus.is-valid{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.b-form-tags.focus.is-invalid{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.b-form-tags.disabled{background-color:#e9ecef}.b-form-tag{font-size:75%;font-weight:400;line-height:1.5;margin-right:.25rem}.b-form-tag.disabled{opacity:.75}.b-form-tag>button.b-form-tag-remove{color:inherit;font-size:125%;line-height:1;float:none;margin-left:.25rem}.form-control-lg .b-form-tag,.form-control-sm .b-form-tag{line-height:1.5}.media-aside{display:flex;margin-right:1rem}.media-aside-right{margin-right:0;margin-left:1rem}.modal-backdrop{opacity:.5}.b-pagination-pills .page-item .page-link{border-radius:50rem!important;margin-left:.25rem;line-height:1}.b-pagination-pills .page-item:first-child .page-link{margin-left:0}.popover.b-popover{display:block;opacity:1;outline:0}.popover.b-popover.fade:not(.show){opacity:0}.popover.b-popover.show{opacity:1}.b-popover-primary.popover{background-color:#cce5ff;border-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-primary.bs-popover-top>.arrow:before{border-top-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-primary.bs-popover-top>.arrow:after{border-top-color:#cce5ff}.b-popover-primary.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-primary.bs-popover-right>.arrow:before{border-right-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-primary.bs-popover-right>.arrow:after{border-right-color:#cce5ff}.b-popover-primary.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-primary.bs-popover-bottom>.arrow:before{border-bottom-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-primary.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-primary.bs-popover-bottom .popover-header:before,.b-popover-primary.bs-popover-bottom>.arrow:after{border-bottom-color:#bdddff}.b-popover-primary.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-primary.bs-popover-left>.arrow:before{border-left-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-primary.bs-popover-left>.arrow:after{border-left-color:#cce5ff}.b-popover-primary .popover-header{color:#212529;background-color:#bdddff;border-bottom-color:#a3d0ff}.b-popover-primary .popover-body{color:#004085}.b-popover-secondary.popover{background-color:#e2e3e5;border-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-secondary.bs-popover-top>.arrow:before{border-top-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-secondary.bs-popover-top>.arrow:after{border-top-color:#e2e3e5}.b-popover-secondary.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-secondary.bs-popover-right>.arrow:before{border-right-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-secondary.bs-popover-right>.arrow:after{border-right-color:#e2e3e5}.b-popover-secondary.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-secondary.bs-popover-bottom>.arrow:before{border-bottom-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-secondary.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-secondary.bs-popover-bottom .popover-header:before,.b-popover-secondary.bs-popover-bottom>.arrow:after{border-bottom-color:#dadbde}.b-popover-secondary.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-secondary.bs-popover-left>.arrow:before{border-left-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-secondary.bs-popover-left>.arrow:after{border-left-color:#e2e3e5}.b-popover-secondary .popover-header{color:#212529;background-color:#dadbde;border-bottom-color:#ccced2}.b-popover-secondary .popover-body{color:#383d41}.b-popover-success.popover{background-color:#d4edda;border-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-success.bs-popover-top>.arrow:before{border-top-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-success.bs-popover-top>.arrow:after{border-top-color:#d4edda}.b-popover-success.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-success.bs-popover-right>.arrow:before{border-right-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-success.bs-popover-right>.arrow:after{border-right-color:#d4edda}.b-popover-success.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-success.bs-popover-bottom>.arrow:before{border-bottom-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-success.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-success.bs-popover-bottom .popover-header:before,.b-popover-success.bs-popover-bottom>.arrow:after{border-bottom-color:#c9e8d1}.b-popover-success.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-success.bs-popover-left>.arrow:before{border-left-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-success.bs-popover-left>.arrow:after{border-left-color:#d4edda}.b-popover-success .popover-header{color:#212529;background-color:#c9e8d1;border-bottom-color:#b7e1c1}.b-popover-success .popover-body{color:#155724}.b-popover-info.popover{background-color:#d1ecf1;border-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-info.bs-popover-top>.arrow:before{border-top-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-info.bs-popover-top>.arrow:after{border-top-color:#d1ecf1}.b-popover-info.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-info.bs-popover-right>.arrow:before{border-right-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-info.bs-popover-right>.arrow:after{border-right-color:#d1ecf1}.b-popover-info.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-info.bs-popover-bottom>.arrow:before{border-bottom-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-info.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-info.bs-popover-bottom .popover-header:before,.b-popover-info.bs-popover-bottom>.arrow:after{border-bottom-color:#c5e7ed}.b-popover-info.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-info.bs-popover-left>.arrow:before{border-left-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-info.bs-popover-left>.arrow:after{border-left-color:#d1ecf1}.b-popover-info .popover-header{color:#212529;background-color:#c5e7ed;border-bottom-color:#b2dfe7}.b-popover-info .popover-body{color:#0c5460}.b-popover-warning.popover{background-color:#fff3cd;border-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-warning.bs-popover-top>.arrow:before{border-top-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-warning.bs-popover-top>.arrow:after{border-top-color:#fff3cd}.b-popover-warning.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-warning.bs-popover-right>.arrow:before{border-right-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-warning.bs-popover-right>.arrow:after{border-right-color:#fff3cd}.b-popover-warning.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-warning.bs-popover-bottom>.arrow:before{border-bottom-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-warning.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-warning.bs-popover-bottom .popover-header:before,.b-popover-warning.bs-popover-bottom>.arrow:after{border-bottom-color:#ffefbe}.b-popover-warning.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-warning.bs-popover-left>.arrow:before{border-left-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-warning.bs-popover-left>.arrow:after{border-left-color:#fff3cd}.b-popover-warning .popover-header{color:#212529;background-color:#ffefbe;border-bottom-color:#ffe9a4}.b-popover-warning .popover-body{color:#856404}.b-popover-danger.popover{background-color:#f8d7da;border-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-danger.bs-popover-top>.arrow:before{border-top-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-danger.bs-popover-top>.arrow:after{border-top-color:#f8d7da}.b-popover-danger.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-danger.bs-popover-right>.arrow:before{border-right-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-danger.bs-popover-right>.arrow:after{border-right-color:#f8d7da}.b-popover-danger.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-danger.bs-popover-bottom>.arrow:before{border-bottom-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-danger.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-danger.bs-popover-bottom .popover-header:before,.b-popover-danger.bs-popover-bottom>.arrow:after{border-bottom-color:#f6cace}.b-popover-danger.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-danger.bs-popover-left>.arrow:before{border-left-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-danger.bs-popover-left>.arrow:after{border-left-color:#f8d7da}.b-popover-danger .popover-header{color:#212529;background-color:#f6cace;border-bottom-color:#f2b4ba}.b-popover-danger .popover-body{color:#721c24}.b-popover-light.popover{background-color:#fefefe;border-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-light.bs-popover-top>.arrow:before{border-top-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-light.bs-popover-top>.arrow:after{border-top-color:#fefefe}.b-popover-light.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-light.bs-popover-right>.arrow:before{border-right-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-light.bs-popover-right>.arrow:after{border-right-color:#fefefe}.b-popover-light.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-light.bs-popover-bottom>.arrow:before{border-bottom-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-light.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-light.bs-popover-bottom .popover-header:before,.b-popover-light.bs-popover-bottom>.arrow:after{border-bottom-color:#f6f6f6}.b-popover-light.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-light.bs-popover-left>.arrow:before{border-left-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-light.bs-popover-left>.arrow:after{border-left-color:#fefefe}.b-popover-light .popover-header{color:#212529;background-color:#f6f6f6;border-bottom-color:#eaeaea}.b-popover-light .popover-body{color:#818182}.b-popover-dark.popover{background-color:#d6d8d9;border-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-dark.bs-popover-top>.arrow:before{border-top-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-dark.bs-popover-top>.arrow:after{border-top-color:#d6d8d9}.b-popover-dark.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-dark.bs-popover-right>.arrow:before{border-right-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-dark.bs-popover-right>.arrow:after{border-right-color:#d6d8d9}.b-popover-dark.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-dark.bs-popover-bottom>.arrow:before{border-bottom-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-dark.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-dark.bs-popover-bottom .popover-header:before,.b-popover-dark.bs-popover-bottom>.arrow:after{border-bottom-color:#ced0d2}.b-popover-dark.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-dark.bs-popover-left>.arrow:before{border-left-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-dark.bs-popover-left>.arrow:after{border-left-color:#d6d8d9}.b-popover-dark .popover-header{color:#212529;background-color:#ced0d2;border-bottom-color:#c1c4c5}.b-popover-dark .popover-body{color:#1b1e21}.b-sidebar-outer{position:fixed;top:0;left:0;right:0;height:0;overflow:visible;z-index:1035}.b-sidebar-backdrop{left:0;z-index:-1;width:100vw;opacity:.6}.b-sidebar,.b-sidebar-backdrop{position:fixed;top:0;height:100vh}.b-sidebar{display:flex;flex-direction:column;width:320px;max-width:100%;max-height:100%;margin:0;outline:0;transform:translateX(0)}.b-sidebar.slide{transition:transform .3s ease-in-out}@media (prefers-reduced-motion:reduce){.b-sidebar.slide{transition:none}}.b-sidebar:not(.b-sidebar-right){left:0;right:auto}.b-sidebar:not(.b-sidebar-right).slide:not(.show){transform:translateX(-100%)}.b-sidebar:not(.b-sidebar-right)>.b-sidebar-header .close{margin-left:auto}.b-sidebar.b-sidebar-right{left:auto;right:0}.b-sidebar.b-sidebar-right.slide:not(.show){transform:translateX(100%)}.b-sidebar.b-sidebar-right>.b-sidebar-header .close{margin-right:auto}.b-sidebar>.b-sidebar-header{font-size:1.5rem;padding:.5rem 1rem;display:flex;flex-direction:row;flex-grow:0;align-items:center}[dir=rtl] .b-sidebar>.b-sidebar-header{flex-direction:row-reverse}.b-sidebar>.b-sidebar-header .close{float:none;font-size:1.5rem}.b-sidebar>.b-sidebar-body{flex-grow:1;height:100%;overflow-y:auto}.b-sidebar>.b-sidebar-footer{flex-grow:0}.b-skeleton-wrapper{cursor:wait}.b-skeleton{position:relative;overflow:hidden;background-color:rgba(0,0,0,.12);cursor:wait;-webkit-mask-image:radial-gradient(#fff,#000);mask-image:radial-gradient(#fff,#000)}.b-skeleton:before{content:" "}.b-skeleton-text{height:1rem;margin-bottom:.25rem;border-radius:.25rem}.b-skeleton-button{width:75px;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem}.b-skeleton-avatar{width:2.5em;height:2.5em;border-radius:50%}.b-skeleton-input{height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;line-height:1.5;border:1px solid #ced4da;border-radius:.25rem}.b-skeleton-icon-wrapper svg{color:rgba(0,0,0,.12)}.b-skeleton-img{height:100%;width:100%}.b-skeleton-animate-wave:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;z-index:0;background:linear-gradient(90deg,transparent,hsla(0,0%,100%,.4),transparent);-webkit-animation:b-skeleton-animate-wave 1.75s linear infinite;animation:b-skeleton-animate-wave 1.75s linear infinite}@media (prefers-reduced-motion:reduce){.b-skeleton-animate-wave:after{background:none;-webkit-animation:none;animation:none}}@-webkit-keyframes b-skeleton-animate-wave{0%{transform:translateX(-100%)}to{transform:translateX(100%)}}@keyframes b-skeleton-animate-wave{0%{transform:translateX(-100%)}to{transform:translateX(100%)}}.b-skeleton-animate-fade{-webkit-animation:b-skeleton-animate-fade .875s ease-in-out infinite alternate;animation:b-skeleton-animate-fade .875s ease-in-out infinite alternate}@media (prefers-reduced-motion:reduce){.b-skeleton-animate-fade{-webkit-animation:none;animation:none}}@-webkit-keyframes b-skeleton-animate-fade{0%{opacity:1}to{opacity:.4}}@keyframes b-skeleton-animate-fade{0%{opacity:1}to{opacity:.4}}.b-skeleton-animate-throb{-webkit-animation:b-skeleton-animate-throb .875s ease-in infinite alternate;animation:b-skeleton-animate-throb .875s ease-in infinite alternate}@media (prefers-reduced-motion:reduce){.b-skeleton-animate-throb{-webkit-animation:none;animation:none}}@-webkit-keyframes b-skeleton-animate-throb{0%{transform:scale(1)}to{transform:scale(.975)}}@keyframes b-skeleton-animate-throb{0%{transform:scale(1)}to{transform:scale(.975)}}.table.b-table.b-table-fixed{table-layout:fixed}.table.b-table.b-table-no-border-collapse{border-collapse:separate;border-spacing:0}.table.b-table[aria-busy=true]{opacity:.55}.table.b-table>tbody>tr.b-table-details>td{border-top:none!important}.table.b-table>caption{caption-side:bottom}.table.b-table.b-table-caption-top>caption{caption-side:top!important}.table.b-table>tbody>.table-active,.table.b-table>tbody>.table-active>td,.table.b-table>tbody>.table-active>th{background-color:rgba(0,0,0,.075)}.table.b-table.table-hover>tbody>tr.table-active:hover td,.table.b-table.table-hover>tbody>tr.table-active:hover th{color:#212529;background-image:linear-gradient(rgba(0,0,0,.075),rgba(0,0,0,.075));background-repeat:no-repeat}.table.b-table>tbody>.bg-active,.table.b-table>tbody>.bg-active>td,.table.b-table>tbody>.bg-active>th{background-color:hsla(0,0%,100%,.075)!important}.table.b-table.table-hover.table-dark>tbody>tr.bg-active:hover td,.table.b-table.table-hover.table-dark>tbody>tr.bg-active:hover th{color:#fff;background-image:linear-gradient(hsla(0,0%,100%,.075),hsla(0,0%,100%,.075));background-repeat:no-repeat}.b-table-sticky-header,.table-responsive,[class*=table-responsive-]{margin-bottom:1rem}.b-table-sticky-header>.table,.table-responsive>.table,[class*=table-responsive-]>.table{margin-bottom:0}.b-table-sticky-header{overflow-y:auto;max-height:300px}@media print{.b-table-sticky-header{overflow-y:visible!important;max-height:none!important}}@supports ((position:-webkit-sticky) or (position:sticky)){.b-table-sticky-header>.table.b-table>thead>tr>th{position:-webkit-sticky;position:sticky;top:0;z-index:2}.b-table-sticky-header>.table.b-table>tbody>tr>.b-table-sticky-column,.b-table-sticky-header>.table.b-table>tfoot>tr>.b-table-sticky-column,.b-table-sticky-header>.table.b-table>thead>tr>.b-table-sticky-column,.table-responsive>.table.b-table>tbody>tr>.b-table-sticky-column,.table-responsive>.table.b-table>tfoot>tr>.b-table-sticky-column,.table-responsive>.table.b-table>thead>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>tbody>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>tfoot>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>thead>tr>.b-table-sticky-column{position:-webkit-sticky;position:sticky;left:0}.b-table-sticky-header>.table.b-table>thead>tr>.b-table-sticky-column,.table-responsive>.table.b-table>thead>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>thead>tr>.b-table-sticky-column{z-index:5}.b-table-sticky-header>.table.b-table>tbody>tr>.b-table-sticky-column,.b-table-sticky-header>.table.b-table>tfoot>tr>.b-table-sticky-column,.table-responsive>.table.b-table>tbody>tr>.b-table-sticky-column,.table-responsive>.table.b-table>tfoot>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>tbody>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>tfoot>tr>.b-table-sticky-column{z-index:2}.table.b-table>tbody>tr>.table-b-table-default,.table.b-table>tfoot>tr>.table-b-table-default,.table.b-table>thead>tr>.table-b-table-default{color:#212529;background-color:#fff}.table.b-table.table-dark>tbody>tr>.bg-b-table-default,.table.b-table.table-dark>tfoot>tr>.bg-b-table-default,.table.b-table.table-dark>thead>tr>.bg-b-table-default{color:#fff;background-color:#343a40}.table.b-table.table-striped>tbody>tr:nth-of-type(odd)>.table-b-table-default{background-image:linear-gradient(rgba(0,0,0,.05),rgba(0,0,0,.05));background-repeat:no-repeat}.table.b-table.table-striped.table-dark>tbody>tr:nth-of-type(odd)>.bg-b-table-default{background-image:linear-gradient(hsla(0,0%,100%,.05),hsla(0,0%,100%,.05));background-repeat:no-repeat}.table.b-table.table-hover>tbody>tr:hover>.table-b-table-default{color:#212529;background-image:linear-gradient(rgba(0,0,0,.075),rgba(0,0,0,.075));background-repeat:no-repeat}.table.b-table.table-hover.table-dark>tbody>tr:hover>.bg-b-table-default{color:#fff;background-image:linear-gradient(hsla(0,0%,100%,.075),hsla(0,0%,100%,.075));background-repeat:no-repeat}}.table.b-table>tfoot>tr>[aria-sort],.table.b-table>thead>tr>[aria-sort]{cursor:pointer;background-image:none;background-repeat:no-repeat;background-size:.65em 1em}.table.b-table>tfoot>tr>[aria-sort]:not(.b-table-sort-icon-left),.table.b-table>thead>tr>[aria-sort]:not(.b-table-sort-icon-left){background-position:right .375rem center;padding-right:calc(.75rem + .65em)}.table.b-table>tfoot>tr>[aria-sort].b-table-sort-icon-left,.table.b-table>thead>tr>[aria-sort].b-table-sort-icon-left{background-position:left .375rem center;padding-left:calc(.75rem + .65em)}.table.b-table>tfoot>tr>[aria-sort=none],.table.b-table>thead>tr>[aria-sort=none]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath opacity='.3' d='M51 1l25 23 24 22H1l25-22zm0 100l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table>tfoot>tr>[aria-sort=ascending],.table.b-table>thead>tr>[aria-sort=ascending]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath d='M51 1l25 23 24 22H1l25-22z'/%3E%3Cpath opacity='.3' d='M51 101l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table>tfoot>tr>[aria-sort=descending],.table.b-table>thead>tr>[aria-sort=descending]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath opacity='.3' d='M51 1l25 23 24 22H1l25-22z'/%3E%3Cpath d='M51 101l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table.table-dark>tfoot>tr>[aria-sort=none],.table.b-table.table-dark>thead>tr>[aria-sort=none],.table.b-table>.thead-dark>tr>[aria-sort=none]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' opacity='.3' d='M51 1l25 23 24 22H1l25-22zm0 100l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table.table-dark>tfoot>tr>[aria-sort=ascending],.table.b-table.table-dark>thead>tr>[aria-sort=ascending],.table.b-table>.thead-dark>tr>[aria-sort=ascending]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M51 1l25 23 24 22H1l25-22z'/%3E%3Cpath fill='%23fff' opacity='.3' d='M51 101l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table.table-dark>tfoot>tr>[aria-sort=descending],.table.b-table.table-dark>thead>tr>[aria-sort=descending],.table.b-table>.thead-dark>tr>[aria-sort=descending]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' opacity='.3' d='M51 1l25 23 24 22H1l25-22z'/%3E%3Cpath fill='%23fff' d='M51 101l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table>tfoot>tr>.table-dark[aria-sort=none],.table.b-table>thead>tr>.table-dark[aria-sort=none]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' opacity='.3' d='M51 1l25 23 24 22H1l25-22zm0 100l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table>tfoot>tr>.table-dark[aria-sort=ascending],.table.b-table>thead>tr>.table-dark[aria-sort=ascending]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M51 1l25 23 24 22H1l25-22z'/%3E%3Cpath fill='%23fff' opacity='.3' d='M51 101l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table>tfoot>tr>.table-dark[aria-sort=descending],.table.b-table>thead>tr>.table-dark[aria-sort=descending]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' opacity='.3' d='M51 1l25 23 24 22H1l25-22z'/%3E%3Cpath fill='%23fff' d='M51 101l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table.table-sm>tfoot>tr>[aria-sort]:not(.b-table-sort-icon-left),.table.b-table.table-sm>thead>tr>[aria-sort]:not(.b-table-sort-icon-left){background-position:right .15rem center;padding-right:calc(.3rem + .65em)}.table.b-table.table-sm>tfoot>tr>[aria-sort].b-table-sort-icon-left,.table.b-table.table-sm>thead>tr>[aria-sort].b-table-sort-icon-left{background-position:left .15rem center;padding-left:calc(.3rem + .65em)}.table.b-table.b-table-selectable:not(.b-table-selectable-no-click)>tbody>tr{cursor:pointer}.table.b-table.b-table-selectable:not(.b-table-selectable-no-click).b-table-selecting.b-table-select-range>tbody>tr{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media (max-width:575.98px){.table.b-table.b-table-stacked-sm{display:block;width:100%}.table.b-table.b-table-stacked-sm>caption,.table.b-table.b-table-stacked-sm>tbody,.table.b-table.b-table-stacked-sm>tbody>tr,.table.b-table.b-table-stacked-sm>tbody>tr>td,.table.b-table.b-table-stacked-sm>tbody>tr>th{display:block}.table.b-table.b-table-stacked-sm>tfoot,.table.b-table.b-table-stacked-sm>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked-sm>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked-sm>thead,.table.b-table.b-table-stacked-sm>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked-sm>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked-sm>caption{caption-side:top!important}.table.b-table.b-table-stacked-sm>tbody>tr>[data-label]:before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 .5rem 0 0;margin:0}.table.b-table.b-table-stacked-sm>tbody>tr>[data-label]:after{display:block;clear:both;content:""}.table.b-table.b-table-stacked-sm>tbody>tr>[data-label]>div{display:inline-block;width:60%;padding:0 0 0 .5rem;margin:0}.table.b-table.b-table-stacked-sm>tbody>tr.bottom-row,.table.b-table.b-table-stacked-sm>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked-sm>tbody>tr>:first-child,.table.b-table.b-table-stacked-sm>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked-sm>tbody>tr>[rowspan]+th{border-top-width:3px}}@media (max-width:767.98px){.table.b-table.b-table-stacked-md{display:block;width:100%}.table.b-table.b-table-stacked-md>caption,.table.b-table.b-table-stacked-md>tbody,.table.b-table.b-table-stacked-md>tbody>tr,.table.b-table.b-table-stacked-md>tbody>tr>td,.table.b-table.b-table-stacked-md>tbody>tr>th{display:block}.table.b-table.b-table-stacked-md>tfoot,.table.b-table.b-table-stacked-md>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked-md>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked-md>thead,.table.b-table.b-table-stacked-md>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked-md>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked-md>caption{caption-side:top!important}.table.b-table.b-table-stacked-md>tbody>tr>[data-label]:before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 .5rem 0 0;margin:0}.table.b-table.b-table-stacked-md>tbody>tr>[data-label]:after{display:block;clear:both;content:""}.table.b-table.b-table-stacked-md>tbody>tr>[data-label]>div{display:inline-block;width:60%;padding:0 0 0 .5rem;margin:0}.table.b-table.b-table-stacked-md>tbody>tr.bottom-row,.table.b-table.b-table-stacked-md>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked-md>tbody>tr>:first-child,.table.b-table.b-table-stacked-md>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked-md>tbody>tr>[rowspan]+th{border-top-width:3px}}@media (max-width:991.98px){.table.b-table.b-table-stacked-lg{display:block;width:100%}.table.b-table.b-table-stacked-lg>caption,.table.b-table.b-table-stacked-lg>tbody,.table.b-table.b-table-stacked-lg>tbody>tr,.table.b-table.b-table-stacked-lg>tbody>tr>td,.table.b-table.b-table-stacked-lg>tbody>tr>th{display:block}.table.b-table.b-table-stacked-lg>tfoot,.table.b-table.b-table-stacked-lg>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked-lg>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked-lg>thead,.table.b-table.b-table-stacked-lg>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked-lg>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked-lg>caption{caption-side:top!important}.table.b-table.b-table-stacked-lg>tbody>tr>[data-label]:before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 .5rem 0 0;margin:0}.table.b-table.b-table-stacked-lg>tbody>tr>[data-label]:after{display:block;clear:both;content:""}.table.b-table.b-table-stacked-lg>tbody>tr>[data-label]>div{display:inline-block;width:60%;padding:0 0 0 .5rem;margin:0}.table.b-table.b-table-stacked-lg>tbody>tr.bottom-row,.table.b-table.b-table-stacked-lg>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked-lg>tbody>tr>:first-child,.table.b-table.b-table-stacked-lg>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked-lg>tbody>tr>[rowspan]+th{border-top-width:3px}}@media (max-width:1199.98px){.table.b-table.b-table-stacked-xl{display:block;width:100%}.table.b-table.b-table-stacked-xl>caption,.table.b-table.b-table-stacked-xl>tbody,.table.b-table.b-table-stacked-xl>tbody>tr,.table.b-table.b-table-stacked-xl>tbody>tr>td,.table.b-table.b-table-stacked-xl>tbody>tr>th{display:block}.table.b-table.b-table-stacked-xl>tfoot,.table.b-table.b-table-stacked-xl>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked-xl>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked-xl>thead,.table.b-table.b-table-stacked-xl>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked-xl>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked-xl>caption{caption-side:top!important}.table.b-table.b-table-stacked-xl>tbody>tr>[data-label]:before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 .5rem 0 0;margin:0}.table.b-table.b-table-stacked-xl>tbody>tr>[data-label]:after{display:block;clear:both;content:""}.table.b-table.b-table-stacked-xl>tbody>tr>[data-label]>div{display:inline-block;width:60%;padding:0 0 0 .5rem;margin:0}.table.b-table.b-table-stacked-xl>tbody>tr.bottom-row,.table.b-table.b-table-stacked-xl>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked-xl>tbody>tr>:first-child,.table.b-table.b-table-stacked-xl>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked-xl>tbody>tr>[rowspan]+th{border-top-width:3px}}.table.b-table.b-table-stacked{display:block;width:100%}.table.b-table.b-table-stacked>caption,.table.b-table.b-table-stacked>tbody,.table.b-table.b-table-stacked>tbody>tr,.table.b-table.b-table-stacked>tbody>tr>td,.table.b-table.b-table-stacked>tbody>tr>th{display:block}.table.b-table.b-table-stacked>tfoot,.table.b-table.b-table-stacked>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked>thead,.table.b-table.b-table-stacked>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked>caption{caption-side:top!important}.table.b-table.b-table-stacked>tbody>tr>[data-label]:before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 .5rem 0 0;margin:0}.table.b-table.b-table-stacked>tbody>tr>[data-label]:after{display:block;clear:both;content:""}.table.b-table.b-table-stacked>tbody>tr>[data-label]>div{display:inline-block;width:60%;padding:0 0 0 .5rem;margin:0}.table.b-table.b-table-stacked>tbody>tr.bottom-row,.table.b-table.b-table-stacked>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked>tbody>tr>:first-child,.table.b-table.b-table-stacked>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked>tbody>tr>[rowspan]+th{border-top-width:3px}.b-time{min-width:150px}.b-time[aria-disabled=true] output,.b-time[aria-readonly=true] output,.b-time output.disabled{background-color:#e9ecef;opacity:1}.b-time[aria-disabled=true] output{pointer-events:none}[dir=rtl] .b-time>.d-flex:not(.flex-column){flex-direction:row-reverse}.b-time .b-time-header{margin-bottom:.5rem}.b-time .b-time-header output{padding:.25rem;font-size:80%}.b-time .b-time-footer{margin-top:.5rem}.b-time .b-time-ampm{margin-left:.5rem}.b-toast{display:block;position:relative;max-width:350px;-webkit-backface-visibility:hidden;backface-visibility:hidden;background-clip:padding-box;z-index:1;border-radius:.25rem}.b-toast .toast{background-color:hsla(0,0%,100%,.85)}.b-toast:not(:last-child){margin-bottom:.75rem}.b-toast.b-toast-solid .toast{background-color:#fff}.b-toast .toast{opacity:1}.b-toast .toast.fade:not(.show){opacity:0}.b-toast .toast .toast-body{display:block}.b-toast-primary .toast{background-color:rgba(230,242,255,.85);border-color:rgba(184,218,255,.85);color:#004085}.b-toast-primary .toast .toast-header{color:#004085;background-color:rgba(204,229,255,.85);border-bottom-color:rgba(184,218,255,.85)}.b-toast-primary.b-toast-solid .toast{background-color:#e6f2ff}.b-toast-secondary .toast{background-color:rgba(239,240,241,.85);border-color:rgba(214,216,219,.85);color:#383d41}.b-toast-secondary .toast .toast-header{color:#383d41;background-color:rgba(226,227,229,.85);border-bottom-color:rgba(214,216,219,.85)}.b-toast-secondary.b-toast-solid .toast{background-color:#eff0f1}.b-toast-success .toast{background-color:rgba(230,245,233,.85);border-color:rgba(195,230,203,.85);color:#155724}.b-toast-success .toast .toast-header{color:#155724;background-color:rgba(212,237,218,.85);border-bottom-color:rgba(195,230,203,.85)}.b-toast-success.b-toast-solid .toast{background-color:#e6f5e9}.b-toast-info .toast{background-color:rgba(229,244,247,.85);border-color:rgba(190,229,235,.85);color:#0c5460}.b-toast-info .toast .toast-header{color:#0c5460;background-color:rgba(209,236,241,.85);border-bottom-color:rgba(190,229,235,.85)}.b-toast-info.b-toast-solid .toast{background-color:#e5f4f7}.b-toast-warning .toast{background-color:rgba(255,249,231,.85);border-color:rgba(255,238,186,.85);color:#856404}.b-toast-warning .toast .toast-header{color:#856404;background-color:rgba(255,243,205,.85);border-bottom-color:rgba(255,238,186,.85)}.b-toast-warning.b-toast-solid .toast{background-color:#fff9e7}.b-toast-danger .toast{background-color:rgba(252,237,238,.85);border-color:rgba(245,198,203,.85);color:#721c24}.b-toast-danger .toast .toast-header{color:#721c24;background-color:rgba(248,215,218,.85);border-bottom-color:rgba(245,198,203,.85)}.b-toast-danger.b-toast-solid .toast{background-color:#fcedee}.b-toast-light .toast{background-color:hsla(0,0%,100%,.85);border-color:rgba(253,253,254,.85);color:#818182}.b-toast-light .toast .toast-header{color:#818182;background-color:hsla(0,0%,99.6%,.85);border-bottom-color:rgba(253,253,254,.85)}.b-toast-light.b-toast-solid .toast{background-color:#fff}.b-toast-dark .toast{background-color:rgba(227,229,229,.85);border-color:rgba(198,200,202,.85);color:#1b1e21}.b-toast-dark .toast .toast-header{color:#1b1e21;background-color:rgba(214,216,217,.85);border-bottom-color:rgba(198,200,202,.85)}.b-toast-dark.b-toast-solid .toast{background-color:#e3e5e5}.b-toaster{z-index:1100}.b-toaster .b-toaster-slot{position:relative;display:block}.b-toaster .b-toaster-slot:empty{display:none!important}.b-toaster.b-toaster-bottom-center,.b-toaster.b-toaster-bottom-full,.b-toaster.b-toaster-bottom-left,.b-toaster.b-toaster-bottom-right,.b-toaster.b-toaster-top-center,.b-toaster.b-toaster-top-full,.b-toaster.b-toaster-top-left,.b-toaster.b-toaster-top-right{position:fixed;left:.5rem;right:.5rem;margin:0;padding:0;height:0;overflow:visible}.b-toaster.b-toaster-bottom-center .b-toaster-slot,.b-toaster.b-toaster-bottom-full .b-toaster-slot,.b-toaster.b-toaster-bottom-left .b-toaster-slot,.b-toaster.b-toaster-bottom-right .b-toaster-slot,.b-toaster.b-toaster-top-center .b-toaster-slot,.b-toaster.b-toaster-top-full .b-toaster-slot,.b-toaster.b-toaster-top-left .b-toaster-slot,.b-toaster.b-toaster-top-right .b-toaster-slot{position:absolute;max-width:350px;width:100%;left:0;right:0;padding:0;margin:0}.b-toaster.b-toaster-bottom-full .b-toaster-slot,.b-toaster.b-toaster-bottom-full .b-toaster-slot .b-toast,.b-toaster.b-toaster-bottom-full .b-toaster-slot .toast,.b-toaster.b-toaster-top-full .b-toaster-slot,.b-toaster.b-toaster-top-full .b-toaster-slot .b-toast,.b-toaster.b-toaster-top-full .b-toaster-slot .toast{width:100%;max-width:100%}.b-toaster.b-toaster-top-center,.b-toaster.b-toaster-top-full,.b-toaster.b-toaster-top-left,.b-toaster.b-toaster-top-right{top:0}.b-toaster.b-toaster-top-center .b-toaster-slot,.b-toaster.b-toaster-top-full .b-toaster-slot,.b-toaster.b-toaster-top-left .b-toaster-slot,.b-toaster.b-toaster-top-right .b-toaster-slot{top:.5rem}.b-toaster.b-toaster-bottom-center,.b-toaster.b-toaster-bottom-full,.b-toaster.b-toaster-bottom-left,.b-toaster.b-toaster-bottom-right{bottom:0}.b-toaster.b-toaster-bottom-center .b-toaster-slot,.b-toaster.b-toaster-bottom-full .b-toaster-slot,.b-toaster.b-toaster-bottom-left .b-toaster-slot,.b-toaster.b-toaster-bottom-right .b-toaster-slot{bottom:.5rem}.b-toaster.b-toaster-bottom-center .b-toaster-slot,.b-toaster.b-toaster-bottom-right .b-toaster-slot,.b-toaster.b-toaster-top-center .b-toaster-slot,.b-toaster.b-toaster-top-right .b-toaster-slot{margin-left:auto}.b-toaster.b-toaster-bottom-center .b-toaster-slot,.b-toaster.b-toaster-bottom-left .b-toaster-slot,.b-toaster.b-toaster-top-center .b-toaster-slot,.b-toaster.b-toaster-top-left .b-toaster-slot{margin-right:auto}.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-enter-active,.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-move,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-enter-active,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-move,.b-toaster.b-toaster-top-left .b-toast.b-toaster-enter-active,.b-toaster.b-toaster-top-left .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-top-left .b-toast.b-toaster-move,.b-toaster.b-toaster-top-right .b-toast.b-toaster-enter-active,.b-toaster.b-toaster-top-right .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-top-right .b-toast.b-toaster-move{transition:transform .175s}.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-enter-active .toast.fade,.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-enter-to .toast.fade,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-enter-active .toast.fade,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-enter-to .toast.fade,.b-toaster.b-toaster-top-left .b-toast.b-toaster-enter-active .toast.fade,.b-toaster.b-toaster-top-left .b-toast.b-toaster-enter-to .toast.fade,.b-toaster.b-toaster-top-right .b-toast.b-toaster-enter-active .toast.fade,.b-toaster.b-toaster-top-right .b-toast.b-toaster-enter-to .toast.fade{transition-delay:.175s}.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-top-left .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-top-right .b-toast.b-toaster-leave-active{position:absolute;transition-delay:.175s}.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-leave-active .toast.fade,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-leave-active .toast.fade,.b-toaster.b-toaster-top-left .b-toast.b-toaster-leave-active .toast.fade,.b-toaster.b-toaster-top-right .b-toast.b-toaster-leave-active .toast.fade{transition-delay:0s}.tooltip.b-tooltip{display:block;opacity:.9;outline:0}.tooltip.b-tooltip.fade:not(.show){opacity:0}.tooltip.b-tooltip.show{opacity:.9}.tooltip.b-tooltip.noninteractive{pointer-events:none}.tooltip.b-tooltip .arrow{margin:0 .25rem}.tooltip.b-tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.bs-tooltip-left .arrow,.tooltip.b-tooltip.bs-tooltip-right .arrow{margin:.25rem 0}.tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-primary.bs-tooltip-top .arrow:before{border-top-color:#007bff}.tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-primary.bs-tooltip-right .arrow:before{border-right-color:#007bff}.tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-primary.bs-tooltip-bottom .arrow:before{border-bottom-color:#007bff}.tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-primary.bs-tooltip-left .arrow:before{border-left-color:#007bff}.tooltip.b-tooltip-primary .tooltip-inner{color:#fff;background-color:#007bff}.tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-secondary.bs-tooltip-top .arrow:before{border-top-color:#6c757d}.tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-secondary.bs-tooltip-right .arrow:before{border-right-color:#6c757d}.tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-secondary.bs-tooltip-bottom .arrow:before{border-bottom-color:#6c757d}.tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-secondary.bs-tooltip-left .arrow:before{border-left-color:#6c757d}.tooltip.b-tooltip-secondary .tooltip-inner{color:#fff;background-color:#6c757d}.tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-success.bs-tooltip-top .arrow:before{border-top-color:#28a745}.tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-success.bs-tooltip-right .arrow:before{border-right-color:#28a745}.tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-success.bs-tooltip-bottom .arrow:before{border-bottom-color:#28a745}.tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-success.bs-tooltip-left .arrow:before{border-left-color:#28a745}.tooltip.b-tooltip-success .tooltip-inner{color:#fff;background-color:#28a745}.tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-info.bs-tooltip-top .arrow:before{border-top-color:#17a2b8}.tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-info.bs-tooltip-right .arrow:before{border-right-color:#17a2b8}.tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-info.bs-tooltip-bottom .arrow:before{border-bottom-color:#17a2b8}.tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-info.bs-tooltip-left .arrow:before{border-left-color:#17a2b8}.tooltip.b-tooltip-info .tooltip-inner{color:#fff;background-color:#17a2b8}.tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-warning.bs-tooltip-top .arrow:before{border-top-color:#ffc107}.tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-warning.bs-tooltip-right .arrow:before{border-right-color:#ffc107}.tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-warning.bs-tooltip-bottom .arrow:before{border-bottom-color:#ffc107}.tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-warning.bs-tooltip-left .arrow:before{border-left-color:#ffc107}.tooltip.b-tooltip-warning .tooltip-inner{color:#212529;background-color:#ffc107}.tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-danger.bs-tooltip-top .arrow:before{border-top-color:#dc3545}.tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-danger.bs-tooltip-right .arrow:before{border-right-color:#dc3545}.tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-danger.bs-tooltip-bottom .arrow:before{border-bottom-color:#dc3545}.tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-danger.bs-tooltip-left .arrow:before{border-left-color:#dc3545}.tooltip.b-tooltip-danger .tooltip-inner{color:#fff;background-color:#dc3545}.tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-light.bs-tooltip-top .arrow:before{border-top-color:#f8f9fa}.tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-light.bs-tooltip-right .arrow:before{border-right-color:#f8f9fa}.tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-light.bs-tooltip-bottom .arrow:before{border-bottom-color:#f8f9fa}.tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-light.bs-tooltip-left .arrow:before{border-left-color:#f8f9fa}.tooltip.b-tooltip-light .tooltip-inner{color:#212529;background-color:#f8f9fa}.tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-dark.bs-tooltip-top .arrow:before{border-top-color:#343a40}.tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-dark.bs-tooltip-right .arrow:before{border-right-color:#343a40}.tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-dark.bs-tooltip-bottom .arrow:before{border-bottom-color:#343a40}.tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-dark.bs-tooltip-left .arrow:before{border-left-color:#343a40}.tooltip.b-tooltip-dark .tooltip-inner{color:#fff;background-color:#343a40}.b-icon.bi{display:inline-block;overflow:visible;vertical-align:-.15em}.b-icon.b-icon-animation-cylon,.b-icon.b-iconstack .b-icon-animation-cylon>g{transform-origin:center;-webkit-animation:b-icon-animation-cylon .75s ease-in-out infinite alternate;animation:b-icon-animation-cylon .75s ease-in-out infinite alternate}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-cylon,.b-icon.b-iconstack .b-icon-animation-cylon>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-cylon-vertical,.b-icon.b-iconstack .b-icon-animation-cylon-vertical>g{transform-origin:center;-webkit-animation:b-icon-animation-cylon-vertical .75s ease-in-out infinite alternate;animation:b-icon-animation-cylon-vertical .75s ease-in-out infinite alternate}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-cylon-vertical,.b-icon.b-iconstack .b-icon-animation-cylon-vertical>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-fade,.b-icon.b-iconstack .b-icon-animation-fade>g{transform-origin:center;-webkit-animation:b-icon-animation-fade .75s ease-in-out infinite alternate;animation:b-icon-animation-fade .75s ease-in-out infinite alternate}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-fade,.b-icon.b-iconstack .b-icon-animation-fade>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-spin,.b-icon.b-iconstack .b-icon-animation-spin>g{transform-origin:center;-webkit-animation:b-icon-animation-spin 2s linear infinite normal;animation:b-icon-animation-spin 2s linear infinite normal}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-spin,.b-icon.b-iconstack .b-icon-animation-spin>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-spin-reverse,.b-icon.b-iconstack .b-icon-animation-spin-reverse>g{transform-origin:center;animation:b-icon-animation-spin 2s linear infinite reverse}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-spin-reverse,.b-icon.b-iconstack .b-icon-animation-spin-reverse>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-spin-pulse,.b-icon.b-iconstack .b-icon-animation-spin-pulse>g{transform-origin:center;-webkit-animation:b-icon-animation-spin 1s steps(8) infinite normal;animation:b-icon-animation-spin 1s steps(8) infinite normal}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-spin-pulse,.b-icon.b-iconstack .b-icon-animation-spin-pulse>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-spin-reverse-pulse,.b-icon.b-iconstack .b-icon-animation-spin-reverse-pulse>g{transform-origin:center;animation:b-icon-animation-spin 1s steps(8) infinite reverse}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-spin-reverse-pulse,.b-icon.b-iconstack .b-icon-animation-spin-reverse-pulse>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-throb,.b-icon.b-iconstack .b-icon-animation-throb>g{transform-origin:center;-webkit-animation:b-icon-animation-throb .75s ease-in-out infinite alternate;animation:b-icon-animation-throb .75s ease-in-out infinite alternate}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-throb,.b-icon.b-iconstack .b-icon-animation-throb>g{-webkit-animation:none;animation:none}}@-webkit-keyframes b-icon-animation-cylon{0%{transform:translateX(-25%)}to{transform:translateX(25%)}}@keyframes b-icon-animation-cylon{0%{transform:translateX(-25%)}to{transform:translateX(25%)}}@-webkit-keyframes b-icon-animation-cylon-vertical{0%{transform:translateY(25%)}to{transform:translateY(-25%)}}@keyframes b-icon-animation-cylon-vertical{0%{transform:translateY(25%)}to{transform:translateY(-25%)}}@-webkit-keyframes b-icon-animation-fade{0%{opacity:.1}to{opacity:1}}@keyframes b-icon-animation-fade{0%{opacity:.1}to{opacity:1}}@-webkit-keyframes b-icon-animation-spin{0%{transform:rotate(0deg)}to{transform:rotate(359deg)}}@keyframes b-icon-animation-spin{0%{transform:rotate(0deg)}to{transform:rotate(359deg)}}@-webkit-keyframes b-icon-animation-throb{0%{opacity:.5;transform:scale(.5)}to{opacity:1;transform:scale(1)}}@keyframes b-icon-animation-throb{0%{opacity:.5;transform:scale(.5)}to{opacity:1;transform:scale(1)}}.btn .b-icon.bi,.dropdown-item .b-icon.bi,.dropdown-toggle .b-icon.bi,.input-group-text .b-icon.bi,.nav-link .b-icon.bi{font-size:125%;vertical-align:text-bottom}fieldset[disabled] .multiselect{pointer-events:none}.multiselect__spinner{position:absolute;right:1px;top:1px;width:48px;height:35px;background:#fff;display:block}.multiselect__spinner:after,.multiselect__spinner:before{position:absolute;content:"";top:50%;left:50%;margin:-8px 0 0 -8px;width:16px;height:16px;border-radius:100%;border:2px solid transparent;border-top-color:#41b883;box-shadow:0 0 0 1px transparent}.multiselect__spinner:before{-webkit-animation:spinning 2.4s cubic-bezier(.41,.26,.2,.62);animation:spinning 2.4s cubic-bezier(.41,.26,.2,.62);-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.multiselect__spinner:after{-webkit-animation:spinning 2.4s cubic-bezier(.51,.09,.21,.8);animation:spinning 2.4s cubic-bezier(.51,.09,.21,.8);-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.multiselect__loading-enter-active,.multiselect__loading-leave-active{transition:opacity .4s ease-in-out;opacity:1}.multiselect__loading-enter,.multiselect__loading-leave-active{opacity:0}.multiselect,.multiselect__input,.multiselect__single{font-family:inherit;font-size:16px;touch-action:manipulation}.multiselect{box-sizing:content-box;display:block;position:relative;width:100%;min-height:40px;text-align:left;color:#35495e}.multiselect *{box-sizing:border-box}.multiselect:focus{outline:none}.multiselect--disabled{background:#ededed;pointer-events:none;opacity:.6}.multiselect--active{z-index:50}.multiselect--active:not(.multiselect--above) .multiselect__current,.multiselect--active:not(.multiselect--above) .multiselect__input,.multiselect--active:not(.multiselect--above) .multiselect__tags{border-bottom-left-radius:0;border-bottom-right-radius:0}.multiselect--active .multiselect__select{transform:rotate(180deg)}.multiselect--above.multiselect--active .multiselect__current,.multiselect--above.multiselect--active .multiselect__input,.multiselect--above.multiselect--active .multiselect__tags{border-top-left-radius:0;border-top-right-radius:0}.multiselect__input,.multiselect__single{position:relative;display:inline-block;min-height:20px;line-height:20px;border:none;border-radius:5px;background:#fff;padding:0 0 0 5px;width:100%;transition:border .1s ease;box-sizing:border-box;margin-bottom:8px;vertical-align:top}.multiselect__input:-ms-input-placeholder{color:#35495e}.multiselect__input::-moz-placeholder{color:#35495e}.multiselect__input::placeholder{color:#35495e}.multiselect__tag~.multiselect__input,.multiselect__tag~.multiselect__single{width:auto}.multiselect__input:hover,.multiselect__single:hover{border-color:#cfcfcf}.multiselect__input:focus,.multiselect__single:focus{border-color:#a8a8a8;outline:none}.multiselect__single{padding-left:5px;margin-bottom:8px}.multiselect__tags-wrap{display:inline}.multiselect__tags{min-height:40px;display:block;padding:8px 40px 0 8px;border-radius:5px;border:1px solid #e8e8e8;background:#fff;font-size:14px}.multiselect__tag{position:relative;display:inline-block;padding:4px 26px 4px 10px;border-radius:5px;margin-right:10px;color:#fff;line-height:1;background:#41b883;margin-bottom:5px;white-space:nowrap;overflow:hidden;max-width:100%;text-overflow:ellipsis}.multiselect__tag-icon{cursor:pointer;margin-left:7px;position:absolute;right:0;top:0;bottom:0;font-weight:700;font-style:normal;width:22px;text-align:center;line-height:22px;transition:all .2s ease;border-radius:5px}.multiselect__tag-icon:after{content:"\D7";color:#266d4d;font-size:14px}.multiselect__tag-icon:focus,.multiselect__tag-icon:hover{background:#369a6e}.multiselect__tag-icon:focus:after,.multiselect__tag-icon:hover:after{color:#fff}.multiselect__current{min-height:40px;overflow:hidden;padding:8px 30px 0 12px;white-space:nowrap;border-radius:5px;border:1px solid #e8e8e8}.multiselect__current,.multiselect__select{line-height:16px;box-sizing:border-box;display:block;margin:0;text-decoration:none;cursor:pointer}.multiselect__select{position:absolute;width:40px;height:38px;right:1px;top:1px;padding:4px 8px;text-align:center;transition:transform .2s ease}.multiselect__select:before{position:relative;right:0;top:65%;color:#999;margin-top:4px;border-color:#999 transparent transparent;border-style:solid;border-width:5px 5px 0;content:""}.multiselect__placeholder{color:#adadad;display:inline-block;margin-bottom:10px;padding-top:2px}.multiselect--active .multiselect__placeholder{display:none}.multiselect__content-wrapper{position:absolute;display:block;background:#fff;width:100%;max-height:240px;overflow:auto;border:1px solid #e8e8e8;border-top:none;border-bottom-left-radius:5px;border-bottom-right-radius:5px;z-index:50;-webkit-overflow-scrolling:touch}.multiselect__content{list-style:none;display:inline-block;padding:0;margin:0;min-width:100%;vertical-align:top}.multiselect--above .multiselect__content-wrapper{bottom:100%;border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:5px;border-top-right-radius:5px;border-bottom:none;border-top:1px solid #e8e8e8}.multiselect__content::webkit-scrollbar{display:none}.multiselect__element{display:block}.multiselect__option{display:block;padding:12px;min-height:40px;line-height:16px;text-decoration:none;text-transform:none;vertical-align:middle;position:relative;cursor:pointer;white-space:nowrap}.multiselect__option:after{top:0;right:0;position:absolute;line-height:40px;padding-right:12px;padding-left:20px;font-size:13px}.multiselect__option--highlight{background:#41b883;outline:none;color:#fff}.multiselect__option--highlight:after{content:attr(data-select);background:#41b883;color:#fff}.multiselect__option--selected{background:#f3f3f3;color:#35495e;font-weight:700}.multiselect__option--selected:after{content:attr(data-selected);color:silver}.multiselect__option--selected.multiselect__option--highlight{background:#ff6a6a;color:#fff}.multiselect__option--selected.multiselect__option--highlight:after{background:#ff6a6a;content:attr(data-deselect);color:#fff}.multiselect--disabled .multiselect__current,.multiselect--disabled .multiselect__select{background:#ededed;color:#a6a6a6}.multiselect__option--disabled{background:#ededed!important;color:#a6a6a6!important;cursor:text;pointer-events:none}.multiselect__option--group{background:#ededed;color:#35495e}.multiselect__option--group.multiselect__option--highlight{background:#35495e;color:#fff}.multiselect__option--group.multiselect__option--highlight:after{background:#35495e}.multiselect__option--disabled.multiselect__option--highlight{background:#dedede}.multiselect__option--group-selected.multiselect__option--highlight{background:#ff6a6a;color:#fff}.multiselect__option--group-selected.multiselect__option--highlight:after{background:#ff6a6a;content:attr(data-deselect);color:#fff}.multiselect-enter-active,.multiselect-leave-active{transition:all .15s ease}.multiselect-enter,.multiselect-leave-active{opacity:0}.multiselect__strong{margin-bottom:8px;line-height:20px;display:inline-block;vertical-align:top}[dir=rtl] .multiselect{text-align:right}[dir=rtl] .multiselect__select{right:auto;left:1px}[dir=rtl] .multiselect__tags{padding:8px 8px 0 40px}[dir=rtl] .multiselect__content{text-align:right}[dir=rtl] .multiselect__option:after{right:auto;left:0}[dir=rtl] .multiselect__clear{right:auto;left:12px}[dir=rtl] .multiselect__spinner{right:auto;left:1px}@-webkit-keyframes spinning{0%{transform:rotate(0)}to{transform:rotate(2turn)}}@keyframes spinning{0%{transform:rotate(0)}to{transform:rotate(2turn)}} \ No newline at end of file + */.bv-no-focus-ring:focus{outline:none}@media (max-width:575.98px){.bv-d-xs-down-none{display:none!important}}@media (max-width:767.98px){.bv-d-sm-down-none{display:none!important}}@media (max-width:991.98px){.bv-d-md-down-none{display:none!important}}@media (max-width:1199.98px){.bv-d-lg-down-none{display:none!important}}.bv-d-xl-down-none{display:none!important}.form-control.focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control.focus.is-valid{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-control.focus.is-invalid{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.b-avatar{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;flex-shrink:0;width:2.5rem;height:2.5rem;font-size:inherit;font-weight:400;line-height:1;max-width:100%;max-height:auto;text-align:center;overflow:visible;position:relative;transition:color .15s ease-in-out,background-color .15s ease-in-out,box-shadow .15s ease-in-out}.b-avatar:focus{outline:0}.b-avatar.btn,.b-avatar[href]{padding:0;border:0}.b-avatar.btn .b-avatar-img img,.b-avatar[href] .b-avatar-img img{transition:transform .15s ease-in-out}.b-avatar.btn:not(:disabled):not(.disabled),.b-avatar[href]:not(:disabled):not(.disabled){cursor:pointer}.b-avatar.btn:not(:disabled):not(.disabled):hover .b-avatar-img img,.b-avatar[href]:not(:disabled):not(.disabled):hover .b-avatar-img img{transform:scale(1.15)}.b-avatar.disabled,.b-avatar:disabled,.b-avatar[disabled]{opacity:.65;pointer-events:none}.b-avatar .b-avatar-custom,.b-avatar .b-avatar-img,.b-avatar .b-avatar-text{border-radius:inherit;width:100%;height:100%;overflow:hidden;display:flex;justify-content:center;align-items:center;-webkit-mask-image:radial-gradient(#fff,#000);mask-image:radial-gradient(#fff,#000)}.b-avatar .b-avatar-text{text-transform:uppercase;white-space:nowrap}.b-avatar[href]{text-decoration:none}.b-avatar>.b-icon{width:60%;height:auto;max-width:100%}.b-avatar .b-avatar-img img{width:100%;height:100%;max-height:auto;border-radius:inherit;-o-object-fit:cover;object-fit:cover}.b-avatar .b-avatar-badge{position:absolute;min-height:1.5em;min-width:1.5em;padding:.25em;line-height:1;border-radius:10em;font-size:70%;font-weight:700;z-index:1}.b-avatar-sm{width:1.5rem;height:1.5rem}.b-avatar-sm .b-avatar-text{font-size:.6rem}.b-avatar-sm .b-avatar-badge{font-size:.42rem}.b-avatar-lg{width:3.5rem;height:3.5rem}.b-avatar-lg .b-avatar-text{font-size:1.4rem}.b-avatar-lg .b-avatar-badge{font-size:.98rem}.b-avatar-group .b-avatar-group-inner{display:flex;flex-wrap:wrap}.b-avatar-group .b-avatar{border:1px solid #dee2e6}.b-avatar-group .btn.b-avatar:hover:not(.disabled):not(disabled),.b-avatar-group a.b-avatar:hover:not(.disabled):not(disabled){z-index:1}.b-calendar{display:inline-flex}.b-calendar .b-calendar-inner{min-width:250px}.b-calendar .b-calendar-header,.b-calendar .b-calendar-nav{margin-bottom:.25rem}.b-calendar .b-calendar-nav .btn{padding:.25rem}.b-calendar output{padding:.25rem;font-size:80%}.b-calendar output.readonly{background-color:#e9ecef;opacity:1}.b-calendar .b-calendar-footer{margin-top:.5rem}.b-calendar .b-calendar-grid{padding:0;margin:0;overflow:hidden}.b-calendar .b-calendar-grid .row{flex-wrap:nowrap}.b-calendar .b-calendar-grid-caption{padding:.25rem}.b-calendar .b-calendar-grid-body .col[data-date] .btn{width:32px;height:32px;font-size:14px;line-height:1;margin:3px auto;padding:9px 0}.b-calendar .btn.disabled,.b-calendar .btn:disabled,.b-calendar .btn[aria-disabled=true]{cursor:default;pointer-events:none}.card-img-left{border-top-left-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-img-right{border-top-right-radius:calc(.25rem - 1px);border-bottom-right-radius:calc(.25rem - 1px)}.dropdown.dropleft .dropdown-toggle.dropdown-toggle-no-caret:before,.dropdown:not(.dropleft) .dropdown-toggle.dropdown-toggle-no-caret:after{display:none!important}.dropdown .dropdown-menu:focus{outline:none}.b-dropdown-form{display:inline-block;padding:.25rem 1.5rem;width:100%;clear:both;font-weight:400}.b-dropdown-form:focus{outline:1px dotted!important;outline:5px auto -webkit-focus-ring-color!important}.b-dropdown-form.disabled,.b-dropdown-form:disabled{outline:0!important;color:#6c757d;pointer-events:none}.b-dropdown-text{display:inline-block;padding:.25rem 1.5rem;margin-bottom:0;width:100%;clear:both;font-weight:lighter}.custom-checkbox.b-custom-control-lg,.input-group-lg .custom-checkbox{font-size:1.25rem;line-height:1.5;padding-left:1.875rem}.custom-checkbox.b-custom-control-lg .custom-control-label:before,.input-group-lg .custom-checkbox .custom-control-label:before{top:.3125rem;left:-1.875rem;width:1.25rem;height:1.25rem;border-radius:.3rem}.custom-checkbox.b-custom-control-lg .custom-control-label:after,.input-group-lg .custom-checkbox .custom-control-label:after{top:.3125rem;left:-1.875rem;width:1.25rem;height:1.25rem;background-size:50% 50%}.custom-checkbox.b-custom-control-sm,.input-group-sm .custom-checkbox{font-size:.875rem;line-height:1.5;padding-left:1.3125rem}.custom-checkbox.b-custom-control-sm .custom-control-label:before,.input-group-sm .custom-checkbox .custom-control-label:before{top:.21875rem;left:-1.3125rem;width:.875rem;height:.875rem;border-radius:.2rem}.custom-checkbox.b-custom-control-sm .custom-control-label:after,.input-group-sm .custom-checkbox .custom-control-label:after{top:.21875rem;left:-1.3125rem;width:.875rem;height:.875rem;background-size:50% 50%}.custom-switch.b-custom-control-lg,.input-group-lg .custom-switch{padding-left:2.8125rem}.custom-switch.b-custom-control-lg .custom-control-label,.input-group-lg .custom-switch .custom-control-label{font-size:1.25rem;line-height:1.5}.custom-switch.b-custom-control-lg .custom-control-label:before,.input-group-lg .custom-switch .custom-control-label:before{top:.3125rem;height:1.25rem;left:-2.8125rem;width:2.1875rem;border-radius:.625rem}.custom-switch.b-custom-control-lg .custom-control-label:after,.input-group-lg .custom-switch .custom-control-label:after{top:calc(.3125rem + 2px);left:calc(-2.8125rem + 2px);width:calc(1.25rem - 4px);height:calc(1.25rem - 4px);border-radius:.625rem;background-size:50% 50%}.custom-switch.b-custom-control-lg .custom-control-input:checked~.custom-control-label:after,.input-group-lg .custom-switch .custom-control-input:checked~.custom-control-label:after{transform:translateX(.9375rem)}.custom-switch.b-custom-control-sm,.input-group-sm .custom-switch{padding-left:1.96875rem}.custom-switch.b-custom-control-sm .custom-control-label,.input-group-sm .custom-switch .custom-control-label{font-size:.875rem;line-height:1.5}.custom-switch.b-custom-control-sm .custom-control-label:before,.input-group-sm .custom-switch .custom-control-label:before{top:.21875rem;left:-1.96875rem;width:1.53125rem;height:.875rem;border-radius:.4375rem}.custom-switch.b-custom-control-sm .custom-control-label:after,.input-group-sm .custom-switch .custom-control-label:after{top:calc(.21875rem + 2px);left:calc(-1.96875rem + 2px);width:calc(.875rem - 4px);height:calc(.875rem - 4px);border-radius:.4375rem;background-size:50% 50%}.custom-switch.b-custom-control-sm .custom-control-input:checked~.custom-control-label:after,.input-group-sm .custom-switch .custom-control-input:checked~.custom-control-label:after{transform:translateX(.65625rem)}.input-group>.input-group-append:last-child>.btn-group:not(:last-child):not(.dropdown-toggle)>.btn,.input-group>.input-group-append:not(:last-child)>.btn-group>.btn,.input-group>.input-group-prepend>.btn-group>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn-group>.btn,.input-group>.input-group-prepend:first-child>.btn-group:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.btn-group>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.b-form-btn-label-control.form-control{display:flex;align-items:stretch;height:auto;padding:0;background-image:none}.input-group .b-form-btn-label-control.form-control{padding:0}.b-form-btn-label-control.form-control[dir=rtl],[dir=rtl] .b-form-btn-label-control.form-control{flex-direction:row-reverse}.b-form-btn-label-control.form-control[dir=rtl]>label,[dir=rtl] .b-form-btn-label-control.form-control>label{text-align:right}.b-form-btn-label-control.form-control>.btn{line-height:1;font-size:inherit;box-shadow:none!important;border:0}.b-form-btn-label-control.form-control>.btn:disabled{pointer-events:none}.b-form-btn-label-control.form-control.is-valid>.btn{color:#28a745}.b-form-btn-label-control.form-control.is-invalid>.btn{color:#dc3545}.b-form-btn-label-control.form-control>.dropdown-menu{padding:.5rem}.b-form-btn-label-control.form-control>.form-control{height:auto;min-height:calc(1.5em + .75rem);padding-left:.25rem;margin:0;border:0;outline:0;background:transparent;word-break:break-word;font-size:inherit;white-space:normal;cursor:pointer}.b-form-btn-label-control.form-control>.form-control.form-control-sm{min-height:calc(1.5em + .5rem)}.b-form-btn-label-control.form-control>.form-control.form-control-lg{min-height:calc(1.5em + 1rem)}.input-group.input-group-sm .b-form-btn-label-control.form-control>.form-control{min-height:calc(1.5em + .5rem);padding-top:.25rem;padding-bottom:.25rem}.input-group.input-group-lg .b-form-btn-label-control.form-control>.form-control{min-height:calc(1.5em + 1rem);padding-top:.5rem;padding-bottom:.5rem}.b-form-btn-label-control.form-control[aria-disabled=true],.b-form-btn-label-control.form-control[aria-readonly=true]{background-color:#e9ecef;opacity:1}.b-form-btn-label-control.form-control[aria-disabled=true]{pointer-events:none}.b-form-btn-label-control.form-control[aria-disabled=true]>label{cursor:default}.b-form-btn-label-control.btn-group>.dropdown-menu{padding:.5rem}.custom-file-label{white-space:nowrap;overflow-x:hidden}.b-custom-control-lg.custom-file,.b-custom-control-lg .custom-file-input,.b-custom-control-lg .custom-file-label,.input-group-lg.custom-file,.input-group-lg .custom-file-input,.input-group-lg .custom-file-label{font-size:1.25rem;height:calc(1.5em + 1rem + 2px)}.b-custom-control-lg .custom-file-label,.b-custom-control-lg .custom-file-label:after,.input-group-lg .custom-file-label,.input-group-lg .custom-file-label:after{padding:.5rem 1rem;line-height:1.5}.b-custom-control-lg .custom-file-label,.input-group-lg .custom-file-label{border-radius:.3rem}.b-custom-control-lg .custom-file-label:after,.input-group-lg .custom-file-label:after{font-size:inherit;height:calc(1.5em + 1rem);border-radius:0 .3rem .3rem 0}.b-custom-control-sm.custom-file,.b-custom-control-sm .custom-file-input,.b-custom-control-sm .custom-file-label,.input-group-sm.custom-file,.input-group-sm .custom-file-input,.input-group-sm .custom-file-label{font-size:.875rem;height:calc(1.5em + .5rem + 2px)}.b-custom-control-sm .custom-file-label,.b-custom-control-sm .custom-file-label:after,.input-group-sm .custom-file-label,.input-group-sm .custom-file-label:after{padding:.25rem .5rem;line-height:1.5}.b-custom-control-sm .custom-file-label,.input-group-sm .custom-file-label{border-radius:.2rem}.b-custom-control-sm .custom-file-label:after,.input-group-sm .custom-file-label:after{font-size:inherit;height:calc(1.5em + .5rem);border-radius:0 .2rem .2rem 0}.form-control.is-invalid,.form-control.is-valid,.was-validated .form-control:invalid,.was-validated .form-control:valid{background-position:right calc(.375em + .1875rem) center}input[type=color].form-control{height:calc(1.5em + .75rem + 2px);padding:.125rem .25rem}.input-group-sm input[type=color].form-control,input[type=color].form-control.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.125rem .25rem}.input-group-lg input[type=color].form-control,input[type=color].form-control.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.125rem .25rem}input[type=color].form-control:disabled{background-color:#adb5bd;opacity:.65}.input-group>.custom-range{position:relative;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.custom-file+.custom-range,.input-group>.custom-range+.custom-file,.input-group>.custom-range+.custom-range,.input-group>.custom-range+.custom-select,.input-group>.custom-range+.form-control,.input-group>.custom-range+.form-control-plaintext,.input-group>.custom-select+.custom-range,.input-group>.form-control+.custom-range,.input-group>.form-control-plaintext+.custom-range{margin-left:-1px}.input-group>.custom-range:focus{z-index:3}.input-group>.custom-range:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-range:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-range{padding:0 .75rem;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;height:calc(1.5em + .75rem + 2px);border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.input-group>.custom-range{transition:none}}.input-group>.custom-range:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.input-group>.custom-range:disabled,.input-group>.custom-range[readonly]{background-color:#e9ecef}.input-group-lg>.custom-range{height:calc(1.5em + 1rem + 2px);padding:0 1rem;border-radius:.3rem}.input-group-sm>.custom-range{height:calc(1.5em + .5rem + 2px);padding:0 .5rem;border-radius:.2rem}.input-group .custom-range.is-valid,.was-validated .input-group .custom-range:valid{border-color:#28a745}.input-group .custom-range.is-valid:focus,.was-validated .input-group .custom-range:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-range.is-valid:focus::-webkit-slider-thumb,.was-validated .custom-range:valid:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #9be7ac}.custom-range.is-valid:focus::-moz-range-thumb,.was-validated .custom-range:valid:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #9be7ac}.custom-range.is-valid:focus::-ms-thumb,.was-validated .custom-range:valid:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #9be7ac}.custom-range.is-valid::-webkit-slider-thumb,.was-validated .custom-range:valid::-webkit-slider-thumb{background-color:#28a745;background-image:none}.custom-range.is-valid::-webkit-slider-thumb:active,.was-validated .custom-range:valid::-webkit-slider-thumb:active{background-color:#9be7ac;background-image:none}.custom-range.is-valid::-webkit-slider-runnable-track,.was-validated .custom-range:valid::-webkit-slider-runnable-track{background-color:rgba(40,167,69,.35)}.custom-range.is-valid::-moz-range-thumb,.was-validated .custom-range:valid::-moz-range-thumb{background-color:#28a745;background-image:none}.custom-range.is-valid::-moz-range-thumb:active,.was-validated .custom-range:valid::-moz-range-thumb:active{background-color:#9be7ac;background-image:none}.custom-range.is-valid::-moz-range-track,.was-validated .custom-range:valid::-moz-range-track{background:rgba(40,167,69,.35)}.custom-range.is-valid~.valid-feedback,.custom-range.is-valid~.valid-tooltip,.was-validated .custom-range:valid~.valid-feedback,.was-validated .custom-range:valid~.valid-tooltip{display:block}.custom-range.is-valid::-ms-thumb,.was-validated .custom-range:valid::-ms-thumb{background-color:#28a745;background-image:none}.custom-range.is-valid::-ms-thumb:active,.was-validated .custom-range:valid::-ms-thumb:active{background-color:#9be7ac;background-image:none}.custom-range.is-valid::-ms-track-lower,.custom-range.is-valid::-ms-track-upper,.was-validated .custom-range:valid::-ms-track-lower,.was-validated .custom-range:valid::-ms-track-upper{background:rgba(40,167,69,.35)}.input-group .custom-range.is-invalid,.was-validated .input-group .custom-range:invalid{border-color:#dc3545}.input-group .custom-range.is-invalid:focus,.was-validated .input-group .custom-range:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-range.is-invalid:focus::-webkit-slider-thumb,.was-validated .custom-range:invalid:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #f6cdd1}.custom-range.is-invalid:focus::-moz-range-thumb,.was-validated .custom-range:invalid:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #f6cdd1}.custom-range.is-invalid:focus::-ms-thumb,.was-validated .custom-range:invalid:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #f6cdd1}.custom-range.is-invalid::-webkit-slider-thumb,.was-validated .custom-range:invalid::-webkit-slider-thumb{background-color:#dc3545;background-image:none}.custom-range.is-invalid::-webkit-slider-thumb:active,.was-validated .custom-range:invalid::-webkit-slider-thumb:active{background-color:#f6cdd1;background-image:none}.custom-range.is-invalid::-webkit-slider-runnable-track,.was-validated .custom-range:invalid::-webkit-slider-runnable-track{background-color:rgba(220,53,69,.35)}.custom-range.is-invalid::-moz-range-thumb,.was-validated .custom-range:invalid::-moz-range-thumb{background-color:#dc3545;background-image:none}.custom-range.is-invalid::-moz-range-thumb:active,.was-validated .custom-range:invalid::-moz-range-thumb:active{background-color:#f6cdd1;background-image:none}.custom-range.is-invalid::-moz-range-track,.was-validated .custom-range:invalid::-moz-range-track{background:rgba(220,53,69,.35)}.custom-range.is-invalid~.invalid-feedback,.custom-range.is-invalid~.invalid-tooltip,.was-validated .custom-range:invalid~.invalid-feedback,.was-validated .custom-range:invalid~.invalid-tooltip{display:block}.custom-range.is-invalid::-ms-thumb,.was-validated .custom-range:invalid::-ms-thumb{background-color:#dc3545;background-image:none}.custom-range.is-invalid::-ms-thumb:active,.was-validated .custom-range:invalid::-ms-thumb:active{background-color:#f6cdd1;background-image:none}.custom-range.is-invalid::-ms-track-lower,.custom-range.is-invalid::-ms-track-upper,.was-validated .custom-range:invalid::-ms-track-lower,.was-validated .custom-range:invalid::-ms-track-upper{background:rgba(220,53,69,.35)}.custom-radio.b-custom-control-lg,.input-group-lg .custom-radio{font-size:1.25rem;line-height:1.5;padding-left:1.875rem}.custom-radio.b-custom-control-lg .custom-control-label:before,.input-group-lg .custom-radio .custom-control-label:before{top:.3125rem;left:-1.875rem;width:1.25rem;height:1.25rem;border-radius:50%}.custom-radio.b-custom-control-lg .custom-control-label:after,.input-group-lg .custom-radio .custom-control-label:after{top:.3125rem;left:-1.875rem;width:1.25rem;height:1.25rem;background:no-repeat 50%/50% 50%}.custom-radio.b-custom-control-sm,.input-group-sm .custom-radio{font-size:.875rem;line-height:1.5;padding-left:1.3125rem}.custom-radio.b-custom-control-sm .custom-control-label:before,.input-group-sm .custom-radio .custom-control-label:before{top:.21875rem;left:-1.3125rem;width:.875rem;height:.875rem;border-radius:50%}.custom-radio.b-custom-control-sm .custom-control-label:after,.input-group-sm .custom-radio .custom-control-label:after{top:.21875rem;left:-1.3125rem;width:.875rem;height:.875rem;background:no-repeat 50%/50% 50%}.b-rating{text-align:center}.b-rating.d-inline-flex{width:auto}.b-rating .b-rating-star,.b-rating .b-rating-value{padding:0 .25em}.b-rating .b-rating-value{min-width:2.5em}.b-rating .b-rating-star{display:inline-flex;justify-content:center;outline:0}.b-rating .b-rating-star .b-rating-icon{display:inline-flex;transition:all .15s ease-in-out}.b-rating.disabled,.b-rating:disabled{background-color:#e9ecef;color:#6c757d}.b-rating:not(.disabled):not(.readonly) .b-rating-star{cursor:pointer}.b-rating:not(.disabled):not(.readonly) .b-rating-star:hover .b-rating-icon,.b-rating:not(.disabled):not(.readonly):focus:not(:hover) .b-rating-star.focused .b-rating-icon{transform:scale(1.5)}.b-rating[dir=rtl] .b-rating-star-half{transform:scaleX(-1)}.b-form-spinbutton{text-align:center;overflow:hidden;background-image:none;padding:0}.b-form-spinbutton[dir=rtl]:not(.flex-column),[dir=rtl] .b-form-spinbutton:not(.flex-column){flex-direction:row-reverse}.b-form-spinbutton output{font-size:inherit;outline:0;border:0;background-color:transparent;width:auto;margin:0;padding:0 .25rem}.b-form-spinbutton output>bdi,.b-form-spinbutton output>div{display:block;min-width:2.25em;height:1.5em}.b-form-spinbutton.flex-column{height:auto;width:auto}.b-form-spinbutton.flex-column output{margin:0 .25rem;padding:.25rem 0}.b-form-spinbutton:not(.d-inline-flex):not(.flex-column){output-width:100%}.b-form-spinbutton.d-inline-flex:not(.flex-column){width:auto}.b-form-spinbutton .btn{line-height:1;box-shadow:none!important}.b-form-spinbutton .btn:disabled{pointer-events:none}.b-form-spinbutton .btn:hover:not(:disabled)>div>.b-icon{transform:scale(1.25)}.b-form-spinbutton.disabled,.b-form-spinbutton.readonly{background-color:#e9ecef}.b-form-spinbutton.disabled{pointer-events:none}.b-form-tags .b-form-tags-list{margin-top:-.25rem}.b-form-tags .b-form-tags-list .b-form-tag,.b-form-tags .b-form-tags-list .b-from-tags-field{margin-top:.25rem}.b-form-tags.focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.b-form-tags.focus.is-valid{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.b-form-tags.focus.is-invalid{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.b-form-tags.disabled{background-color:#e9ecef}.b-form-tag{font-size:75%;font-weight:400;line-height:1.5;margin-right:.25rem}.b-form-tag.disabled{opacity:.75}.b-form-tag>button.b-form-tag-remove{color:inherit;font-size:125%;line-height:1;float:none;margin-left:.25rem}.form-control-lg .b-form-tag,.form-control-sm .b-form-tag{line-height:1.5}.media-aside{display:flex;margin-right:1rem}.media-aside-right{margin-right:0;margin-left:1rem}.modal-backdrop{opacity:.5}.b-pagination-pills .page-item .page-link{border-radius:50rem!important;margin-left:.25rem;line-height:1}.b-pagination-pills .page-item:first-child .page-link{margin-left:0}.popover.b-popover{display:block;opacity:1;outline:0}.popover.b-popover.fade:not(.show){opacity:0}.popover.b-popover.show{opacity:1}.b-popover-primary.popover{background-color:#cce5ff;border-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-primary.bs-popover-top>.arrow:before{border-top-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-primary.bs-popover-top>.arrow:after{border-top-color:#cce5ff}.b-popover-primary.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-primary.bs-popover-right>.arrow:before{border-right-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-primary.bs-popover-right>.arrow:after{border-right-color:#cce5ff}.b-popover-primary.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-primary.bs-popover-bottom>.arrow:before{border-bottom-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-primary.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-primary.bs-popover-bottom .popover-header:before,.b-popover-primary.bs-popover-bottom>.arrow:after{border-bottom-color:#bdddff}.b-popover-primary.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-primary.bs-popover-left>.arrow:before{border-left-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-primary.bs-popover-left>.arrow:after{border-left-color:#cce5ff}.b-popover-primary .popover-header{color:#212529;background-color:#bdddff;border-bottom-color:#a3d0ff}.b-popover-primary .popover-body{color:#004085}.b-popover-secondary.popover{background-color:#e2e3e5;border-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-secondary.bs-popover-top>.arrow:before{border-top-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-secondary.bs-popover-top>.arrow:after{border-top-color:#e2e3e5}.b-popover-secondary.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-secondary.bs-popover-right>.arrow:before{border-right-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-secondary.bs-popover-right>.arrow:after{border-right-color:#e2e3e5}.b-popover-secondary.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-secondary.bs-popover-bottom>.arrow:before{border-bottom-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-secondary.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-secondary.bs-popover-bottom .popover-header:before,.b-popover-secondary.bs-popover-bottom>.arrow:after{border-bottom-color:#dadbde}.b-popover-secondary.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-secondary.bs-popover-left>.arrow:before{border-left-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-secondary.bs-popover-left>.arrow:after{border-left-color:#e2e3e5}.b-popover-secondary .popover-header{color:#212529;background-color:#dadbde;border-bottom-color:#ccced2}.b-popover-secondary .popover-body{color:#383d41}.b-popover-success.popover{background-color:#d4edda;border-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-success.bs-popover-top>.arrow:before{border-top-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-success.bs-popover-top>.arrow:after{border-top-color:#d4edda}.b-popover-success.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-success.bs-popover-right>.arrow:before{border-right-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-success.bs-popover-right>.arrow:after{border-right-color:#d4edda}.b-popover-success.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-success.bs-popover-bottom>.arrow:before{border-bottom-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-success.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-success.bs-popover-bottom .popover-header:before,.b-popover-success.bs-popover-bottom>.arrow:after{border-bottom-color:#c9e8d1}.b-popover-success.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-success.bs-popover-left>.arrow:before{border-left-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-success.bs-popover-left>.arrow:after{border-left-color:#d4edda}.b-popover-success .popover-header{color:#212529;background-color:#c9e8d1;border-bottom-color:#b7e1c1}.b-popover-success .popover-body{color:#155724}.b-popover-info.popover{background-color:#d1ecf1;border-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-info.bs-popover-top>.arrow:before{border-top-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-info.bs-popover-top>.arrow:after{border-top-color:#d1ecf1}.b-popover-info.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-info.bs-popover-right>.arrow:before{border-right-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-info.bs-popover-right>.arrow:after{border-right-color:#d1ecf1}.b-popover-info.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-info.bs-popover-bottom>.arrow:before{border-bottom-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-info.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-info.bs-popover-bottom .popover-header:before,.b-popover-info.bs-popover-bottom>.arrow:after{border-bottom-color:#c5e7ed}.b-popover-info.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-info.bs-popover-left>.arrow:before{border-left-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-info.bs-popover-left>.arrow:after{border-left-color:#d1ecf1}.b-popover-info .popover-header{color:#212529;background-color:#c5e7ed;border-bottom-color:#b2dfe7}.b-popover-info .popover-body{color:#0c5460}.b-popover-warning.popover{background-color:#fff3cd;border-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-warning.bs-popover-top>.arrow:before{border-top-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-warning.bs-popover-top>.arrow:after{border-top-color:#fff3cd}.b-popover-warning.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-warning.bs-popover-right>.arrow:before{border-right-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-warning.bs-popover-right>.arrow:after{border-right-color:#fff3cd}.b-popover-warning.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-warning.bs-popover-bottom>.arrow:before{border-bottom-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-warning.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-warning.bs-popover-bottom .popover-header:before,.b-popover-warning.bs-popover-bottom>.arrow:after{border-bottom-color:#ffefbe}.b-popover-warning.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-warning.bs-popover-left>.arrow:before{border-left-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-warning.bs-popover-left>.arrow:after{border-left-color:#fff3cd}.b-popover-warning .popover-header{color:#212529;background-color:#ffefbe;border-bottom-color:#ffe9a4}.b-popover-warning .popover-body{color:#856404}.b-popover-danger.popover{background-color:#f8d7da;border-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-danger.bs-popover-top>.arrow:before{border-top-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-danger.bs-popover-top>.arrow:after{border-top-color:#f8d7da}.b-popover-danger.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-danger.bs-popover-right>.arrow:before{border-right-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-danger.bs-popover-right>.arrow:after{border-right-color:#f8d7da}.b-popover-danger.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-danger.bs-popover-bottom>.arrow:before{border-bottom-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-danger.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-danger.bs-popover-bottom .popover-header:before,.b-popover-danger.bs-popover-bottom>.arrow:after{border-bottom-color:#f6cace}.b-popover-danger.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-danger.bs-popover-left>.arrow:before{border-left-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-danger.bs-popover-left>.arrow:after{border-left-color:#f8d7da}.b-popover-danger .popover-header{color:#212529;background-color:#f6cace;border-bottom-color:#f2b4ba}.b-popover-danger .popover-body{color:#721c24}.b-popover-light.popover{background-color:#fefefe;border-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-light.bs-popover-top>.arrow:before{border-top-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-light.bs-popover-top>.arrow:after{border-top-color:#fefefe}.b-popover-light.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-light.bs-popover-right>.arrow:before{border-right-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-light.bs-popover-right>.arrow:after{border-right-color:#fefefe}.b-popover-light.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-light.bs-popover-bottom>.arrow:before{border-bottom-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-light.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-light.bs-popover-bottom .popover-header:before,.b-popover-light.bs-popover-bottom>.arrow:after{border-bottom-color:#f6f6f6}.b-popover-light.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-light.bs-popover-left>.arrow:before{border-left-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-light.bs-popover-left>.arrow:after{border-left-color:#fefefe}.b-popover-light .popover-header{color:#212529;background-color:#f6f6f6;border-bottom-color:#eaeaea}.b-popover-light .popover-body{color:#818182}.b-popover-dark.popover{background-color:#d6d8d9;border-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=top]>.arrow:before,.b-popover-dark.bs-popover-top>.arrow:before{border-top-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=top]>.arrow:after,.b-popover-dark.bs-popover-top>.arrow:after{border-top-color:#d6d8d9}.b-popover-dark.bs-popover-auto[x-placement^=right]>.arrow:before,.b-popover-dark.bs-popover-right>.arrow:before{border-right-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=right]>.arrow:after,.b-popover-dark.bs-popover-right>.arrow:after{border-right-color:#d6d8d9}.b-popover-dark.bs-popover-auto[x-placement^=bottom]>.arrow:before,.b-popover-dark.bs-popover-bottom>.arrow:before{border-bottom-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=bottom] .popover-header:before,.b-popover-dark.bs-popover-auto[x-placement^=bottom]>.arrow:after,.b-popover-dark.bs-popover-bottom .popover-header:before,.b-popover-dark.bs-popover-bottom>.arrow:after{border-bottom-color:#ced0d2}.b-popover-dark.bs-popover-auto[x-placement^=left]>.arrow:before,.b-popover-dark.bs-popover-left>.arrow:before{border-left-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=left]>.arrow:after,.b-popover-dark.bs-popover-left>.arrow:after{border-left-color:#d6d8d9}.b-popover-dark .popover-header{color:#212529;background-color:#ced0d2;border-bottom-color:#c1c4c5}.b-popover-dark .popover-body{color:#1b1e21}.b-sidebar-outer{position:fixed;top:0;left:0;right:0;height:0;overflow:visible;z-index:1035}.b-sidebar-backdrop{left:0;z-index:-1;width:100vw;opacity:.6}.b-sidebar,.b-sidebar-backdrop{position:fixed;top:0;height:100vh}.b-sidebar{display:flex;flex-direction:column;width:320px;max-width:100%;max-height:100%;margin:0;outline:0;transform:translateX(0)}.b-sidebar.slide{transition:transform .3s ease-in-out}@media (prefers-reduced-motion:reduce){.b-sidebar.slide{transition:none}}.b-sidebar:not(.b-sidebar-right){left:0;right:auto}.b-sidebar:not(.b-sidebar-right).slide:not(.show){transform:translateX(-100%)}.b-sidebar:not(.b-sidebar-right)>.b-sidebar-header .close{margin-left:auto}.b-sidebar.b-sidebar-right{left:auto;right:0}.b-sidebar.b-sidebar-right.slide:not(.show){transform:translateX(100%)}.b-sidebar.b-sidebar-right>.b-sidebar-header .close{margin-right:auto}.b-sidebar>.b-sidebar-header{font-size:1.5rem;padding:.5rem 1rem;display:flex;flex-direction:row;flex-grow:0;align-items:center}[dir=rtl] .b-sidebar>.b-sidebar-header{flex-direction:row-reverse}.b-sidebar>.b-sidebar-header .close{float:none;font-size:1.5rem}.b-sidebar>.b-sidebar-body{flex-grow:1;height:100%;overflow-y:auto}.b-sidebar>.b-sidebar-footer{flex-grow:0}.b-skeleton-wrapper{cursor:wait}.b-skeleton{position:relative;overflow:hidden;background-color:rgba(0,0,0,.12);cursor:wait;-webkit-mask-image:radial-gradient(#fff,#000);mask-image:radial-gradient(#fff,#000)}.b-skeleton:before{content:" "}.b-skeleton-text{height:1rem;margin-bottom:.25rem;border-radius:.25rem}.b-skeleton-button{width:75px;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem}.b-skeleton-avatar{width:2.5em;height:2.5em;border-radius:50%}.b-skeleton-input{height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;line-height:1.5;border:1px solid #ced4da;border-radius:.25rem}.b-skeleton-icon-wrapper svg{color:rgba(0,0,0,.12)}.b-skeleton-img{height:100%;width:100%}.b-skeleton-animate-wave:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;z-index:0;background:linear-gradient(90deg,transparent,hsla(0,0%,100%,.4),transparent);-webkit-animation:b-skeleton-animate-wave 1.75s linear infinite;animation:b-skeleton-animate-wave 1.75s linear infinite}@media (prefers-reduced-motion:reduce){.b-skeleton-animate-wave:after{background:none;-webkit-animation:none;animation:none}}@-webkit-keyframes b-skeleton-animate-wave{0%{transform:translateX(-100%)}to{transform:translateX(100%)}}@keyframes b-skeleton-animate-wave{0%{transform:translateX(-100%)}to{transform:translateX(100%)}}.b-skeleton-animate-fade{-webkit-animation:b-skeleton-animate-fade .875s ease-in-out infinite alternate;animation:b-skeleton-animate-fade .875s ease-in-out infinite alternate}@media (prefers-reduced-motion:reduce){.b-skeleton-animate-fade{-webkit-animation:none;animation:none}}@-webkit-keyframes b-skeleton-animate-fade{0%{opacity:1}to{opacity:.4}}@keyframes b-skeleton-animate-fade{0%{opacity:1}to{opacity:.4}}.b-skeleton-animate-throb{-webkit-animation:b-skeleton-animate-throb .875s ease-in infinite alternate;animation:b-skeleton-animate-throb .875s ease-in infinite alternate}@media (prefers-reduced-motion:reduce){.b-skeleton-animate-throb{-webkit-animation:none;animation:none}}@-webkit-keyframes b-skeleton-animate-throb{0%{transform:scale(1)}to{transform:scale(.975)}}@keyframes b-skeleton-animate-throb{0%{transform:scale(1)}to{transform:scale(.975)}}.table.b-table.b-table-fixed{table-layout:fixed}.table.b-table.b-table-no-border-collapse{border-collapse:separate;border-spacing:0}.table.b-table[aria-busy=true]{opacity:.55}.table.b-table>tbody>tr.b-table-details>td{border-top:none!important}.table.b-table>caption{caption-side:bottom}.table.b-table.b-table-caption-top>caption{caption-side:top!important}.table.b-table>tbody>.table-active,.table.b-table>tbody>.table-active>td,.table.b-table>tbody>.table-active>th{background-color:rgba(0,0,0,.075)}.table.b-table.table-hover>tbody>tr.table-active:hover td,.table.b-table.table-hover>tbody>tr.table-active:hover th{color:#212529;background-image:linear-gradient(rgba(0,0,0,.075),rgba(0,0,0,.075));background-repeat:no-repeat}.table.b-table>tbody>.bg-active,.table.b-table>tbody>.bg-active>td,.table.b-table>tbody>.bg-active>th{background-color:hsla(0,0%,100%,.075)!important}.table.b-table.table-hover.table-dark>tbody>tr.bg-active:hover td,.table.b-table.table-hover.table-dark>tbody>tr.bg-active:hover th{color:#fff;background-image:linear-gradient(hsla(0,0%,100%,.075),hsla(0,0%,100%,.075));background-repeat:no-repeat}.b-table-sticky-header,.table-responsive,[class*=table-responsive-]{margin-bottom:1rem}.b-table-sticky-header>.table,.table-responsive>.table,[class*=table-responsive-]>.table{margin-bottom:0}.b-table-sticky-header{overflow-y:auto;max-height:300px}@media print{.b-table-sticky-header{overflow-y:visible!important;max-height:none!important}}@supports (position:sticky){.b-table-sticky-header>.table.b-table>thead>tr>th{position:sticky;top:0;z-index:2}.b-table-sticky-header>.table.b-table>tbody>tr>.b-table-sticky-column,.b-table-sticky-header>.table.b-table>tfoot>tr>.b-table-sticky-column,.b-table-sticky-header>.table.b-table>thead>tr>.b-table-sticky-column,.table-responsive>.table.b-table>tbody>tr>.b-table-sticky-column,.table-responsive>.table.b-table>tfoot>tr>.b-table-sticky-column,.table-responsive>.table.b-table>thead>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>tbody>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>tfoot>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>thead>tr>.b-table-sticky-column{position:sticky;left:0}.b-table-sticky-header>.table.b-table>thead>tr>.b-table-sticky-column,.table-responsive>.table.b-table>thead>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>thead>tr>.b-table-sticky-column{z-index:5}.b-table-sticky-header>.table.b-table>tbody>tr>.b-table-sticky-column,.b-table-sticky-header>.table.b-table>tfoot>tr>.b-table-sticky-column,.table-responsive>.table.b-table>tbody>tr>.b-table-sticky-column,.table-responsive>.table.b-table>tfoot>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>tbody>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>tfoot>tr>.b-table-sticky-column{z-index:2}.table.b-table>tbody>tr>.table-b-table-default,.table.b-table>tfoot>tr>.table-b-table-default,.table.b-table>thead>tr>.table-b-table-default{color:#212529;background-color:#fff}.table.b-table.table-dark>tbody>tr>.bg-b-table-default,.table.b-table.table-dark>tfoot>tr>.bg-b-table-default,.table.b-table.table-dark>thead>tr>.bg-b-table-default{color:#fff;background-color:#343a40}.table.b-table.table-striped>tbody>tr:nth-of-type(odd)>.table-b-table-default{background-image:linear-gradient(rgba(0,0,0,.05),rgba(0,0,0,.05));background-repeat:no-repeat}.table.b-table.table-striped.table-dark>tbody>tr:nth-of-type(odd)>.bg-b-table-default{background-image:linear-gradient(hsla(0,0%,100%,.05),hsla(0,0%,100%,.05));background-repeat:no-repeat}.table.b-table.table-hover>tbody>tr:hover>.table-b-table-default{color:#212529;background-image:linear-gradient(rgba(0,0,0,.075),rgba(0,0,0,.075));background-repeat:no-repeat}.table.b-table.table-hover.table-dark>tbody>tr:hover>.bg-b-table-default{color:#fff;background-image:linear-gradient(hsla(0,0%,100%,.075),hsla(0,0%,100%,.075));background-repeat:no-repeat}}.table.b-table>tfoot>tr>[aria-sort],.table.b-table>thead>tr>[aria-sort]{cursor:pointer;background-image:none;background-repeat:no-repeat;background-size:.65em 1em}.table.b-table>tfoot>tr>[aria-sort]:not(.b-table-sort-icon-left),.table.b-table>thead>tr>[aria-sort]:not(.b-table-sort-icon-left){background-position:right .375rem center;padding-right:calc(.75rem + .65em)}.table.b-table>tfoot>tr>[aria-sort].b-table-sort-icon-left,.table.b-table>thead>tr>[aria-sort].b-table-sort-icon-left{background-position:left .375rem center;padding-left:calc(.75rem + .65em)}.table.b-table>tfoot>tr>[aria-sort=none],.table.b-table>thead>tr>[aria-sort=none]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath opacity='.3' d='M51 1l25 23 24 22H1l25-22zm0 100l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table>tfoot>tr>[aria-sort=ascending],.table.b-table>thead>tr>[aria-sort=ascending]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath d='M51 1l25 23 24 22H1l25-22z'/%3E%3Cpath opacity='.3' d='M51 101l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table>tfoot>tr>[aria-sort=descending],.table.b-table>thead>tr>[aria-sort=descending]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath opacity='.3' d='M51 1l25 23 24 22H1l25-22z'/%3E%3Cpath d='M51 101l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table.table-dark>tfoot>tr>[aria-sort=none],.table.b-table.table-dark>thead>tr>[aria-sort=none],.table.b-table>.thead-dark>tr>[aria-sort=none]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' opacity='.3' d='M51 1l25 23 24 22H1l25-22zm0 100l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table.table-dark>tfoot>tr>[aria-sort=ascending],.table.b-table.table-dark>thead>tr>[aria-sort=ascending],.table.b-table>.thead-dark>tr>[aria-sort=ascending]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M51 1l25 23 24 22H1l25-22z'/%3E%3Cpath fill='%23fff' opacity='.3' d='M51 101l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table.table-dark>tfoot>tr>[aria-sort=descending],.table.b-table.table-dark>thead>tr>[aria-sort=descending],.table.b-table>.thead-dark>tr>[aria-sort=descending]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' opacity='.3' d='M51 1l25 23 24 22H1l25-22z'/%3E%3Cpath fill='%23fff' d='M51 101l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table>tfoot>tr>.table-dark[aria-sort=none],.table.b-table>thead>tr>.table-dark[aria-sort=none]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' opacity='.3' d='M51 1l25 23 24 22H1l25-22zm0 100l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table>tfoot>tr>.table-dark[aria-sort=ascending],.table.b-table>thead>tr>.table-dark[aria-sort=ascending]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M51 1l25 23 24 22H1l25-22z'/%3E%3Cpath fill='%23fff' opacity='.3' d='M51 101l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table>tfoot>tr>.table-dark[aria-sort=descending],.table.b-table>thead>tr>.table-dark[aria-sort=descending]{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' opacity='.3' d='M51 1l25 23 24 22H1l25-22z'/%3E%3Cpath fill='%23fff' d='M51 101l25-23 24-22H1l25 22z'/%3E%3C/svg%3E")}.table.b-table.table-sm>tfoot>tr>[aria-sort]:not(.b-table-sort-icon-left),.table.b-table.table-sm>thead>tr>[aria-sort]:not(.b-table-sort-icon-left){background-position:right .15rem center;padding-right:calc(.3rem + .65em)}.table.b-table.table-sm>tfoot>tr>[aria-sort].b-table-sort-icon-left,.table.b-table.table-sm>thead>tr>[aria-sort].b-table-sort-icon-left{background-position:left .15rem center;padding-left:calc(.3rem + .65em)}.table.b-table.b-table-selectable:not(.b-table-selectable-no-click)>tbody>tr{cursor:pointer}.table.b-table.b-table-selectable:not(.b-table-selectable-no-click).b-table-selecting.b-table-select-range>tbody>tr{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media (max-width:575.98px){.table.b-table.b-table-stacked-sm{display:block;width:100%}.table.b-table.b-table-stacked-sm>caption,.table.b-table.b-table-stacked-sm>tbody,.table.b-table.b-table-stacked-sm>tbody>tr,.table.b-table.b-table-stacked-sm>tbody>tr>td,.table.b-table.b-table-stacked-sm>tbody>tr>th{display:block}.table.b-table.b-table-stacked-sm>tfoot,.table.b-table.b-table-stacked-sm>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked-sm>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked-sm>thead,.table.b-table.b-table-stacked-sm>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked-sm>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked-sm>caption{caption-side:top!important}.table.b-table.b-table-stacked-sm>tbody>tr>[data-label]:before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 .5rem 0 0;margin:0}.table.b-table.b-table-stacked-sm>tbody>tr>[data-label]:after{display:block;clear:both;content:""}.table.b-table.b-table-stacked-sm>tbody>tr>[data-label]>div{display:inline-block;width:60%;padding:0 0 0 .5rem;margin:0}.table.b-table.b-table-stacked-sm>tbody>tr.bottom-row,.table.b-table.b-table-stacked-sm>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked-sm>tbody>tr>:first-child,.table.b-table.b-table-stacked-sm>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked-sm>tbody>tr>[rowspan]+th{border-top-width:3px}}@media (max-width:767.98px){.table.b-table.b-table-stacked-md{display:block;width:100%}.table.b-table.b-table-stacked-md>caption,.table.b-table.b-table-stacked-md>tbody,.table.b-table.b-table-stacked-md>tbody>tr,.table.b-table.b-table-stacked-md>tbody>tr>td,.table.b-table.b-table-stacked-md>tbody>tr>th{display:block}.table.b-table.b-table-stacked-md>tfoot,.table.b-table.b-table-stacked-md>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked-md>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked-md>thead,.table.b-table.b-table-stacked-md>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked-md>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked-md>caption{caption-side:top!important}.table.b-table.b-table-stacked-md>tbody>tr>[data-label]:before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 .5rem 0 0;margin:0}.table.b-table.b-table-stacked-md>tbody>tr>[data-label]:after{display:block;clear:both;content:""}.table.b-table.b-table-stacked-md>tbody>tr>[data-label]>div{display:inline-block;width:60%;padding:0 0 0 .5rem;margin:0}.table.b-table.b-table-stacked-md>tbody>tr.bottom-row,.table.b-table.b-table-stacked-md>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked-md>tbody>tr>:first-child,.table.b-table.b-table-stacked-md>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked-md>tbody>tr>[rowspan]+th{border-top-width:3px}}@media (max-width:991.98px){.table.b-table.b-table-stacked-lg{display:block;width:100%}.table.b-table.b-table-stacked-lg>caption,.table.b-table.b-table-stacked-lg>tbody,.table.b-table.b-table-stacked-lg>tbody>tr,.table.b-table.b-table-stacked-lg>tbody>tr>td,.table.b-table.b-table-stacked-lg>tbody>tr>th{display:block}.table.b-table.b-table-stacked-lg>tfoot,.table.b-table.b-table-stacked-lg>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked-lg>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked-lg>thead,.table.b-table.b-table-stacked-lg>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked-lg>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked-lg>caption{caption-side:top!important}.table.b-table.b-table-stacked-lg>tbody>tr>[data-label]:before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 .5rem 0 0;margin:0}.table.b-table.b-table-stacked-lg>tbody>tr>[data-label]:after{display:block;clear:both;content:""}.table.b-table.b-table-stacked-lg>tbody>tr>[data-label]>div{display:inline-block;width:60%;padding:0 0 0 .5rem;margin:0}.table.b-table.b-table-stacked-lg>tbody>tr.bottom-row,.table.b-table.b-table-stacked-lg>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked-lg>tbody>tr>:first-child,.table.b-table.b-table-stacked-lg>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked-lg>tbody>tr>[rowspan]+th{border-top-width:3px}}@media (max-width:1199.98px){.table.b-table.b-table-stacked-xl{display:block;width:100%}.table.b-table.b-table-stacked-xl>caption,.table.b-table.b-table-stacked-xl>tbody,.table.b-table.b-table-stacked-xl>tbody>tr,.table.b-table.b-table-stacked-xl>tbody>tr>td,.table.b-table.b-table-stacked-xl>tbody>tr>th{display:block}.table.b-table.b-table-stacked-xl>tfoot,.table.b-table.b-table-stacked-xl>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked-xl>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked-xl>thead,.table.b-table.b-table-stacked-xl>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked-xl>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked-xl>caption{caption-side:top!important}.table.b-table.b-table-stacked-xl>tbody>tr>[data-label]:before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 .5rem 0 0;margin:0}.table.b-table.b-table-stacked-xl>tbody>tr>[data-label]:after{display:block;clear:both;content:""}.table.b-table.b-table-stacked-xl>tbody>tr>[data-label]>div{display:inline-block;width:60%;padding:0 0 0 .5rem;margin:0}.table.b-table.b-table-stacked-xl>tbody>tr.bottom-row,.table.b-table.b-table-stacked-xl>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked-xl>tbody>tr>:first-child,.table.b-table.b-table-stacked-xl>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked-xl>tbody>tr>[rowspan]+th{border-top-width:3px}}.table.b-table.b-table-stacked{display:block;width:100%}.table.b-table.b-table-stacked>caption,.table.b-table.b-table-stacked>tbody,.table.b-table.b-table-stacked>tbody>tr,.table.b-table.b-table-stacked>tbody>tr>td,.table.b-table.b-table-stacked>tbody>tr>th{display:block}.table.b-table.b-table-stacked>tfoot,.table.b-table.b-table-stacked>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked>thead,.table.b-table.b-table-stacked>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked>caption{caption-side:top!important}.table.b-table.b-table-stacked>tbody>tr>[data-label]:before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 .5rem 0 0;margin:0}.table.b-table.b-table-stacked>tbody>tr>[data-label]:after{display:block;clear:both;content:""}.table.b-table.b-table-stacked>tbody>tr>[data-label]>div{display:inline-block;width:60%;padding:0 0 0 .5rem;margin:0}.table.b-table.b-table-stacked>tbody>tr.bottom-row,.table.b-table.b-table-stacked>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked>tbody>tr>:first-child,.table.b-table.b-table-stacked>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked>tbody>tr>[rowspan]+th{border-top-width:3px}.b-time{min-width:150px}.b-time[aria-disabled=true] output,.b-time[aria-readonly=true] output,.b-time output.disabled{background-color:#e9ecef;opacity:1}.b-time[aria-disabled=true] output{pointer-events:none}[dir=rtl] .b-time>.d-flex:not(.flex-column){flex-direction:row-reverse}.b-time .b-time-header{margin-bottom:.5rem}.b-time .b-time-header output{padding:.25rem;font-size:80%}.b-time .b-time-footer{margin-top:.5rem}.b-time .b-time-ampm{margin-left:.5rem}.b-toast{display:block;position:relative;max-width:350px;-webkit-backface-visibility:hidden;backface-visibility:hidden;background-clip:padding-box;z-index:1;border-radius:.25rem}.b-toast .toast{background-color:hsla(0,0%,100%,.85)}.b-toast:not(:last-child){margin-bottom:.75rem}.b-toast.b-toast-solid .toast{background-color:#fff}.b-toast .toast{opacity:1}.b-toast .toast.fade:not(.show){opacity:0}.b-toast .toast .toast-body{display:block}.b-toast-primary .toast{background-color:rgba(230,242,255,.85);border-color:rgba(184,218,255,.85);color:#004085}.b-toast-primary .toast .toast-header{color:#004085;background-color:rgba(204,229,255,.85);border-bottom-color:rgba(184,218,255,.85)}.b-toast-primary.b-toast-solid .toast{background-color:#e6f2ff}.b-toast-secondary .toast{background-color:rgba(239,240,241,.85);border-color:rgba(214,216,219,.85);color:#383d41}.b-toast-secondary .toast .toast-header{color:#383d41;background-color:rgba(226,227,229,.85);border-bottom-color:rgba(214,216,219,.85)}.b-toast-secondary.b-toast-solid .toast{background-color:#eff0f1}.b-toast-success .toast{background-color:rgba(230,245,233,.85);border-color:rgba(195,230,203,.85);color:#155724}.b-toast-success .toast .toast-header{color:#155724;background-color:rgba(212,237,218,.85);border-bottom-color:rgba(195,230,203,.85)}.b-toast-success.b-toast-solid .toast{background-color:#e6f5e9}.b-toast-info .toast{background-color:rgba(229,244,247,.85);border-color:rgba(190,229,235,.85);color:#0c5460}.b-toast-info .toast .toast-header{color:#0c5460;background-color:rgba(209,236,241,.85);border-bottom-color:rgba(190,229,235,.85)}.b-toast-info.b-toast-solid .toast{background-color:#e5f4f7}.b-toast-warning .toast{background-color:rgba(255,249,231,.85);border-color:rgba(255,238,186,.85);color:#856404}.b-toast-warning .toast .toast-header{color:#856404;background-color:rgba(255,243,205,.85);border-bottom-color:rgba(255,238,186,.85)}.b-toast-warning.b-toast-solid .toast{background-color:#fff9e7}.b-toast-danger .toast{background-color:rgba(252,237,238,.85);border-color:rgba(245,198,203,.85);color:#721c24}.b-toast-danger .toast .toast-header{color:#721c24;background-color:rgba(248,215,218,.85);border-bottom-color:rgba(245,198,203,.85)}.b-toast-danger.b-toast-solid .toast{background-color:#fcedee}.b-toast-light .toast{background-color:hsla(0,0%,100%,.85);border-color:rgba(253,253,254,.85);color:#818182}.b-toast-light .toast .toast-header{color:#818182;background-color:hsla(0,0%,99.6%,.85);border-bottom-color:rgba(253,253,254,.85)}.b-toast-light.b-toast-solid .toast{background-color:#fff}.b-toast-dark .toast{background-color:rgba(227,229,229,.85);border-color:rgba(198,200,202,.85);color:#1b1e21}.b-toast-dark .toast .toast-header{color:#1b1e21;background-color:rgba(214,216,217,.85);border-bottom-color:rgba(198,200,202,.85)}.b-toast-dark.b-toast-solid .toast{background-color:#e3e5e5}.b-toaster{z-index:1100}.b-toaster .b-toaster-slot{position:relative;display:block}.b-toaster .b-toaster-slot:empty{display:none!important}.b-toaster.b-toaster-bottom-center,.b-toaster.b-toaster-bottom-full,.b-toaster.b-toaster-bottom-left,.b-toaster.b-toaster-bottom-right,.b-toaster.b-toaster-top-center,.b-toaster.b-toaster-top-full,.b-toaster.b-toaster-top-left,.b-toaster.b-toaster-top-right{position:fixed;left:.5rem;right:.5rem;margin:0;padding:0;height:0;overflow:visible}.b-toaster.b-toaster-bottom-center .b-toaster-slot,.b-toaster.b-toaster-bottom-full .b-toaster-slot,.b-toaster.b-toaster-bottom-left .b-toaster-slot,.b-toaster.b-toaster-bottom-right .b-toaster-slot,.b-toaster.b-toaster-top-center .b-toaster-slot,.b-toaster.b-toaster-top-full .b-toaster-slot,.b-toaster.b-toaster-top-left .b-toaster-slot,.b-toaster.b-toaster-top-right .b-toaster-slot{position:absolute;max-width:350px;width:100%;left:0;right:0;padding:0;margin:0}.b-toaster.b-toaster-bottom-full .b-toaster-slot,.b-toaster.b-toaster-bottom-full .b-toaster-slot .b-toast,.b-toaster.b-toaster-bottom-full .b-toaster-slot .toast,.b-toaster.b-toaster-top-full .b-toaster-slot,.b-toaster.b-toaster-top-full .b-toaster-slot .b-toast,.b-toaster.b-toaster-top-full .b-toaster-slot .toast{width:100%;max-width:100%}.b-toaster.b-toaster-top-center,.b-toaster.b-toaster-top-full,.b-toaster.b-toaster-top-left,.b-toaster.b-toaster-top-right{top:0}.b-toaster.b-toaster-top-center .b-toaster-slot,.b-toaster.b-toaster-top-full .b-toaster-slot,.b-toaster.b-toaster-top-left .b-toaster-slot,.b-toaster.b-toaster-top-right .b-toaster-slot{top:.5rem}.b-toaster.b-toaster-bottom-center,.b-toaster.b-toaster-bottom-full,.b-toaster.b-toaster-bottom-left,.b-toaster.b-toaster-bottom-right{bottom:0}.b-toaster.b-toaster-bottom-center .b-toaster-slot,.b-toaster.b-toaster-bottom-full .b-toaster-slot,.b-toaster.b-toaster-bottom-left .b-toaster-slot,.b-toaster.b-toaster-bottom-right .b-toaster-slot{bottom:.5rem}.b-toaster.b-toaster-bottom-center .b-toaster-slot,.b-toaster.b-toaster-bottom-right .b-toaster-slot,.b-toaster.b-toaster-top-center .b-toaster-slot,.b-toaster.b-toaster-top-right .b-toaster-slot{margin-left:auto}.b-toaster.b-toaster-bottom-center .b-toaster-slot,.b-toaster.b-toaster-bottom-left .b-toaster-slot,.b-toaster.b-toaster-top-center .b-toaster-slot,.b-toaster.b-toaster-top-left .b-toaster-slot{margin-right:auto}.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-enter-active,.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-move,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-enter-active,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-move,.b-toaster.b-toaster-top-left .b-toast.b-toaster-enter-active,.b-toaster.b-toaster-top-left .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-top-left .b-toast.b-toaster-move,.b-toaster.b-toaster-top-right .b-toast.b-toaster-enter-active,.b-toaster.b-toaster-top-right .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-top-right .b-toast.b-toaster-move{transition:transform .175s}.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-enter-active .toast.fade,.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-enter-to .toast.fade,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-enter-active .toast.fade,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-enter-to .toast.fade,.b-toaster.b-toaster-top-left .b-toast.b-toaster-enter-active .toast.fade,.b-toaster.b-toaster-top-left .b-toast.b-toaster-enter-to .toast.fade,.b-toaster.b-toaster-top-right .b-toast.b-toaster-enter-active .toast.fade,.b-toaster.b-toaster-top-right .b-toast.b-toaster-enter-to .toast.fade{transition-delay:.175s}.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-top-left .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-top-right .b-toast.b-toaster-leave-active{position:absolute;transition-delay:.175s}.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-leave-active .toast.fade,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-leave-active .toast.fade,.b-toaster.b-toaster-top-left .b-toast.b-toaster-leave-active .toast.fade,.b-toaster.b-toaster-top-right .b-toast.b-toaster-leave-active .toast.fade{transition-delay:0s}.tooltip.b-tooltip{display:block;opacity:.9;outline:0}.tooltip.b-tooltip.fade:not(.show){opacity:0}.tooltip.b-tooltip.show{opacity:.9}.tooltip.b-tooltip.noninteractive{pointer-events:none}.tooltip.b-tooltip .arrow{margin:0 .25rem}.tooltip.b-tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.b-tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.b-tooltip.bs-tooltip-left .arrow,.tooltip.b-tooltip.bs-tooltip-right .arrow{margin:.25rem 0}.tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-primary.bs-tooltip-top .arrow:before{border-top-color:#007bff}.tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-primary.bs-tooltip-right .arrow:before{border-right-color:#007bff}.tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-primary.bs-tooltip-bottom .arrow:before{border-bottom-color:#007bff}.tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-primary.bs-tooltip-left .arrow:before{border-left-color:#007bff}.tooltip.b-tooltip-primary .tooltip-inner{color:#fff;background-color:#007bff}.tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-secondary.bs-tooltip-top .arrow:before{border-top-color:#6c757d}.tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-secondary.bs-tooltip-right .arrow:before{border-right-color:#6c757d}.tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-secondary.bs-tooltip-bottom .arrow:before{border-bottom-color:#6c757d}.tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-secondary.bs-tooltip-left .arrow:before{border-left-color:#6c757d}.tooltip.b-tooltip-secondary .tooltip-inner{color:#fff;background-color:#6c757d}.tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-success.bs-tooltip-top .arrow:before{border-top-color:#28a745}.tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-success.bs-tooltip-right .arrow:before{border-right-color:#28a745}.tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-success.bs-tooltip-bottom .arrow:before{border-bottom-color:#28a745}.tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-success.bs-tooltip-left .arrow:before{border-left-color:#28a745}.tooltip.b-tooltip-success .tooltip-inner{color:#fff;background-color:#28a745}.tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-info.bs-tooltip-top .arrow:before{border-top-color:#17a2b8}.tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-info.bs-tooltip-right .arrow:before{border-right-color:#17a2b8}.tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-info.bs-tooltip-bottom .arrow:before{border-bottom-color:#17a2b8}.tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-info.bs-tooltip-left .arrow:before{border-left-color:#17a2b8}.tooltip.b-tooltip-info .tooltip-inner{color:#fff;background-color:#17a2b8}.tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-warning.bs-tooltip-top .arrow:before{border-top-color:#ffc107}.tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-warning.bs-tooltip-right .arrow:before{border-right-color:#ffc107}.tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-warning.bs-tooltip-bottom .arrow:before{border-bottom-color:#ffc107}.tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-warning.bs-tooltip-left .arrow:before{border-left-color:#ffc107}.tooltip.b-tooltip-warning .tooltip-inner{color:#212529;background-color:#ffc107}.tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-danger.bs-tooltip-top .arrow:before{border-top-color:#dc3545}.tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-danger.bs-tooltip-right .arrow:before{border-right-color:#dc3545}.tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-danger.bs-tooltip-bottom .arrow:before{border-bottom-color:#dc3545}.tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-danger.bs-tooltip-left .arrow:before{border-left-color:#dc3545}.tooltip.b-tooltip-danger .tooltip-inner{color:#fff;background-color:#dc3545}.tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-light.bs-tooltip-top .arrow:before{border-top-color:#f8f9fa}.tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-light.bs-tooltip-right .arrow:before{border-right-color:#f8f9fa}.tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-light.bs-tooltip-bottom .arrow:before{border-bottom-color:#f8f9fa}.tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-light.bs-tooltip-left .arrow:before{border-left-color:#f8f9fa}.tooltip.b-tooltip-light .tooltip-inner{color:#212529;background-color:#f8f9fa}.tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=top] .arrow:before,.tooltip.b-tooltip-dark.bs-tooltip-top .arrow:before{border-top-color:#343a40}.tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=right] .arrow:before,.tooltip.b-tooltip-dark.bs-tooltip-right .arrow:before{border-right-color:#343a40}.tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=bottom] .arrow:before,.tooltip.b-tooltip-dark.bs-tooltip-bottom .arrow:before{border-bottom-color:#343a40}.tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=left] .arrow:before,.tooltip.b-tooltip-dark.bs-tooltip-left .arrow:before{border-left-color:#343a40}.tooltip.b-tooltip-dark .tooltip-inner{color:#fff;background-color:#343a40}.b-icon.bi{display:inline-block;overflow:visible;vertical-align:-.15em}.b-icon.b-icon-animation-cylon,.b-icon.b-iconstack .b-icon-animation-cylon>g{transform-origin:center;-webkit-animation:b-icon-animation-cylon .75s ease-in-out infinite alternate;animation:b-icon-animation-cylon .75s ease-in-out infinite alternate}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-cylon,.b-icon.b-iconstack .b-icon-animation-cylon>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-cylon-vertical,.b-icon.b-iconstack .b-icon-animation-cylon-vertical>g{transform-origin:center;-webkit-animation:b-icon-animation-cylon-vertical .75s ease-in-out infinite alternate;animation:b-icon-animation-cylon-vertical .75s ease-in-out infinite alternate}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-cylon-vertical,.b-icon.b-iconstack .b-icon-animation-cylon-vertical>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-fade,.b-icon.b-iconstack .b-icon-animation-fade>g{transform-origin:center;-webkit-animation:b-icon-animation-fade .75s ease-in-out infinite alternate;animation:b-icon-animation-fade .75s ease-in-out infinite alternate}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-fade,.b-icon.b-iconstack .b-icon-animation-fade>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-spin,.b-icon.b-iconstack .b-icon-animation-spin>g{transform-origin:center;-webkit-animation:b-icon-animation-spin 2s linear infinite normal;animation:b-icon-animation-spin 2s linear infinite normal}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-spin,.b-icon.b-iconstack .b-icon-animation-spin>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-spin-reverse,.b-icon.b-iconstack .b-icon-animation-spin-reverse>g{transform-origin:center;animation:b-icon-animation-spin 2s linear infinite reverse}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-spin-reverse,.b-icon.b-iconstack .b-icon-animation-spin-reverse>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-spin-pulse,.b-icon.b-iconstack .b-icon-animation-spin-pulse>g{transform-origin:center;-webkit-animation:b-icon-animation-spin 1s steps(8) infinite normal;animation:b-icon-animation-spin 1s steps(8) infinite normal}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-spin-pulse,.b-icon.b-iconstack .b-icon-animation-spin-pulse>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-spin-reverse-pulse,.b-icon.b-iconstack .b-icon-animation-spin-reverse-pulse>g{transform-origin:center;animation:b-icon-animation-spin 1s steps(8) infinite reverse}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-spin-reverse-pulse,.b-icon.b-iconstack .b-icon-animation-spin-reverse-pulse>g{-webkit-animation:none;animation:none}}.b-icon.b-icon-animation-throb,.b-icon.b-iconstack .b-icon-animation-throb>g{transform-origin:center;-webkit-animation:b-icon-animation-throb .75s ease-in-out infinite alternate;animation:b-icon-animation-throb .75s ease-in-out infinite alternate}@media (prefers-reduced-motion:reduce){.b-icon.b-icon-animation-throb,.b-icon.b-iconstack .b-icon-animation-throb>g{-webkit-animation:none;animation:none}}@-webkit-keyframes b-icon-animation-cylon{0%{transform:translateX(-25%)}to{transform:translateX(25%)}}@keyframes b-icon-animation-cylon{0%{transform:translateX(-25%)}to{transform:translateX(25%)}}@-webkit-keyframes b-icon-animation-cylon-vertical{0%{transform:translateY(25%)}to{transform:translateY(-25%)}}@keyframes b-icon-animation-cylon-vertical{0%{transform:translateY(25%)}to{transform:translateY(-25%)}}@-webkit-keyframes b-icon-animation-fade{0%{opacity:.1}to{opacity:1}}@keyframes b-icon-animation-fade{0%{opacity:.1}to{opacity:1}}@-webkit-keyframes b-icon-animation-spin{0%{transform:rotate(0deg)}to{transform:rotate(359deg)}}@keyframes b-icon-animation-spin{0%{transform:rotate(0deg)}to{transform:rotate(359deg)}}@-webkit-keyframes b-icon-animation-throb{0%{opacity:.5;transform:scale(.5)}to{opacity:1;transform:scale(1)}}@keyframes b-icon-animation-throb{0%{opacity:.5;transform:scale(.5)}to{opacity:1;transform:scale(1)}}.btn .b-icon.bi,.dropdown-item .b-icon.bi,.dropdown-toggle .b-icon.bi,.input-group-text .b-icon.bi,.nav-link .b-icon.bi{font-size:125%;vertical-align:text-bottom}fieldset[disabled] .multiselect{pointer-events:none}.multiselect__spinner{position:absolute;right:1px;top:1px;width:48px;height:35px;background:#fff;display:block}.multiselect__spinner:after,.multiselect__spinner:before{position:absolute;content:"";top:50%;left:50%;margin:-8px 0 0 -8px;width:16px;height:16px;border-radius:100%;border:2px solid transparent;border-top-color:#41b883;box-shadow:0 0 0 1px transparent}.multiselect__spinner:before{-webkit-animation:spinning 2.4s cubic-bezier(.41,.26,.2,.62);animation:spinning 2.4s cubic-bezier(.41,.26,.2,.62);-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.multiselect__spinner:after{-webkit-animation:spinning 2.4s cubic-bezier(.51,.09,.21,.8);animation:spinning 2.4s cubic-bezier(.51,.09,.21,.8);-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.multiselect__loading-enter-active,.multiselect__loading-leave-active{transition:opacity .4s ease-in-out;opacity:1}.multiselect__loading-enter,.multiselect__loading-leave-active{opacity:0}.multiselect,.multiselect__input,.multiselect__single{font-family:inherit;font-size:16px;touch-action:manipulation}.multiselect{box-sizing:content-box;display:block;position:relative;width:100%;min-height:40px;text-align:left;color:#35495e}.multiselect *{box-sizing:border-box}.multiselect:focus{outline:none}.multiselect--disabled{background:#ededed;pointer-events:none;opacity:.6}.multiselect--active{z-index:50}.multiselect--active:not(.multiselect--above) .multiselect__current,.multiselect--active:not(.multiselect--above) .multiselect__input,.multiselect--active:not(.multiselect--above) .multiselect__tags{border-bottom-left-radius:0;border-bottom-right-radius:0}.multiselect--active .multiselect__select{transform:rotate(180deg)}.multiselect--above.multiselect--active .multiselect__current,.multiselect--above.multiselect--active .multiselect__input,.multiselect--above.multiselect--active .multiselect__tags{border-top-left-radius:0;border-top-right-radius:0}.multiselect__input,.multiselect__single{position:relative;display:inline-block;min-height:20px;line-height:20px;border:none;border-radius:5px;background:#fff;padding:0 0 0 5px;width:100%;transition:border .1s ease;box-sizing:border-box;margin-bottom:8px;vertical-align:top}.multiselect__input:-ms-input-placeholder{color:#35495e}.multiselect__input::-moz-placeholder{color:#35495e}.multiselect__input::placeholder{color:#35495e}.multiselect__tag~.multiselect__input,.multiselect__tag~.multiselect__single{width:auto}.multiselect__input:hover,.multiselect__single:hover{border-color:#cfcfcf}.multiselect__input:focus,.multiselect__single:focus{border-color:#a8a8a8;outline:none}.multiselect__single{padding-left:5px;margin-bottom:8px}.multiselect__tags-wrap{display:inline}.multiselect__tags{min-height:40px;display:block;padding:8px 40px 0 8px;border-radius:5px;border:1px solid #e8e8e8;background:#fff;font-size:14px}.multiselect__tag{position:relative;display:inline-block;padding:4px 26px 4px 10px;border-radius:5px;margin-right:10px;color:#fff;line-height:1;background:#41b883;margin-bottom:5px;white-space:nowrap;overflow:hidden;max-width:100%;text-overflow:ellipsis}.multiselect__tag-icon{cursor:pointer;margin-left:7px;position:absolute;right:0;top:0;bottom:0;font-weight:700;font-style:normal;width:22px;text-align:center;line-height:22px;transition:all .2s ease;border-radius:5px}.multiselect__tag-icon:after{content:"\D7";color:#266d4d;font-size:14px}.multiselect__tag-icon:focus,.multiselect__tag-icon:hover{background:#369a6e}.multiselect__tag-icon:focus:after,.multiselect__tag-icon:hover:after{color:#fff}.multiselect__current{min-height:40px;overflow:hidden;padding:8px 30px 0 12px;white-space:nowrap;border-radius:5px;border:1px solid #e8e8e8}.multiselect__current,.multiselect__select{line-height:16px;box-sizing:border-box;display:block;margin:0;text-decoration:none;cursor:pointer}.multiselect__select{position:absolute;width:40px;height:38px;right:1px;top:1px;padding:4px 8px;text-align:center;transition:transform .2s ease}.multiselect__select:before{position:relative;right:0;top:65%;color:#999;margin-top:4px;border-color:#999 transparent transparent;border-style:solid;border-width:5px 5px 0;content:""}.multiselect__placeholder{color:#adadad;display:inline-block;margin-bottom:10px;padding-top:2px}.multiselect--active .multiselect__placeholder{display:none}.multiselect__content-wrapper{position:absolute;display:block;background:#fff;width:100%;max-height:240px;overflow:auto;border:1px solid #e8e8e8;border-top:none;border-bottom-left-radius:5px;border-bottom-right-radius:5px;z-index:50;-webkit-overflow-scrolling:touch}.multiselect__content{list-style:none;display:inline-block;padding:0;margin:0;min-width:100%;vertical-align:top}.multiselect--above .multiselect__content-wrapper{bottom:100%;border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:5px;border-top-right-radius:5px;border-bottom:none;border-top:1px solid #e8e8e8}.multiselect__content::webkit-scrollbar{display:none}.multiselect__element{display:block}.multiselect__option{display:block;padding:12px;min-height:40px;line-height:16px;text-decoration:none;text-transform:none;vertical-align:middle;position:relative;cursor:pointer;white-space:nowrap}.multiselect__option:after{top:0;right:0;position:absolute;line-height:40px;padding-right:12px;padding-left:20px;font-size:13px}.multiselect__option--highlight{background:#41b883;outline:none;color:#fff}.multiselect__option--highlight:after{content:attr(data-select);background:#41b883;color:#fff}.multiselect__option--selected{background:#f3f3f3;color:#35495e;font-weight:700}.multiselect__option--selected:after{content:attr(data-selected);color:silver}.multiselect__option--selected.multiselect__option--highlight{background:#ff6a6a;color:#fff}.multiselect__option--selected.multiselect__option--highlight:after{background:#ff6a6a;content:attr(data-deselect);color:#fff}.multiselect--disabled .multiselect__current,.multiselect--disabled .multiselect__select{background:#ededed;color:#a6a6a6}.multiselect__option--disabled{background:#ededed!important;color:#a6a6a6!important;cursor:text;pointer-events:none}.multiselect__option--group{background:#ededed;color:#35495e}.multiselect__option--group.multiselect__option--highlight{background:#35495e;color:#fff}.multiselect__option--group.multiselect__option--highlight:after{background:#35495e}.multiselect__option--disabled.multiselect__option--highlight{background:#dedede}.multiselect__option--group-selected.multiselect__option--highlight{background:#ff6a6a;color:#fff}.multiselect__option--group-selected.multiselect__option--highlight:after{background:#ff6a6a;content:attr(data-deselect);color:#fff}.multiselect-enter-active,.multiselect-leave-active{transition:all .15s ease}.multiselect-enter,.multiselect-leave-active{opacity:0}.multiselect__strong{margin-bottom:8px;line-height:20px;display:inline-block;vertical-align:top}[dir=rtl] .multiselect{text-align:right}[dir=rtl] .multiselect__select{right:auto;left:1px}[dir=rtl] .multiselect__tags{padding:8px 8px 0 40px}[dir=rtl] .multiselect__content{text-align:right}[dir=rtl] .multiselect__option:after{right:auto;left:0}[dir=rtl] .multiselect__clear{right:auto;left:12px}[dir=rtl] .multiselect__spinner{right:auto;left:1px}@-webkit-keyframes spinning{0%{transform:rotate(0)}to{transform:rotate(2turn)}}@keyframes spinning{0%{transform:rotate(0)}to{transform:rotate(2turn)}} \ No newline at end of file diff --git a/cookbook/static/vue/js/chunk-vendors.js b/cookbook/static/vue/js/chunk-vendors.js index 245259a7..ce946b58 100644 --- a/cookbook/static/vue/js/chunk-vendors.js +++ b/cookbook/static/vue/js/chunk-vendors.js @@ -34,7 +34,7 @@ var e=t.defineLocale("th",{months:"มกราคม_กุมภาพัน //! moment.js locale configuration var e={words:{ss:["секунда","секунде","секунди"],m:["један минут","једне минуте"],mm:["минут","минуте","минута"],h:["један сат","једног сата"],hh:["сат","сата","сати"],dd:["дан","дана","дана"],MM:["месец","месеца","месеци"],yy:["година","године","година"]},correctGrammaticalCase:function(t,e){return 1===t?e[0]:t>=2&&t<=4?e[1]:e[2]},translate:function(t,n,r){var i=e.words[r];return 1===r.length?n?i[0]:i[1]:t+" "+e.correctGrammaticalCase(t,i)}},n=t.defineLocale("sr-cyrl",{months:"јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар".split("_"),monthsShort:"јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.".split("_"),monthsParseExact:!0,weekdays:"недеља_понедељак_уторак_среда_четвртак_петак_субота".split("_"),weekdaysShort:"нед._пон._уто._сре._чет._пет._суб.".split("_"),weekdaysMin:"не_по_ут_ср_че_пе_су".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D. M. YYYY.",LL:"D. MMMM YYYY.",LLL:"D. MMMM YYYY. H:mm",LLLL:"dddd, D. MMMM YYYY. H:mm"},calendar:{sameDay:"[данас у] LT",nextDay:"[сутра у] LT",nextWeek:function(){switch(this.day()){case 0:return"[у] [недељу] [у] LT";case 3:return"[у] [среду] [у] LT";case 6:return"[у] [суботу] [у] LT";case 1:case 2:case 4:case 5:return"[у] dddd [у] LT"}},lastDay:"[јуче у] LT",lastWeek:function(){var t=["[прошле] [недеље] [у] LT","[прошлог] [понедељка] [у] LT","[прошлог] [уторка] [у] LT","[прошле] [среде] [у] LT","[прошлог] [четвртка] [у] LT","[прошлог] [петка] [у] LT","[прошле] [суботе] [у] LT"];return t[this.day()]},sameElse:"L"},relativeTime:{future:"за %s",past:"пре %s",s:"неколико секунди",ss:e.translate,m:e.translate,mm:e.translate,h:e.translate,hh:e.translate,d:"дан",dd:e.translate,M:"месец",MM:e.translate,y:"годину",yy:e.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return n}))},"14c3":function(t,e,n){var r=n("c6b6"),i=n("9263");t.exports=function(t,e){var n=t.exec;if("function"===typeof n){var a=n.call(t,e);if("object"!==typeof a)throw TypeError("RegExp exec method returned something other than an Object or null");return a}if("RegExp"!==r(t))throw TypeError("RegExp#exec called on incompatible receiver");return i.call(t,e)}},"159b":function(t,e,n){var r=n("da84"),i=n("fdbc"),a=n("17c2"),o=n("9112");for(var s in i){var c=r[s],u=c&&c.prototype;if(u&&u.forEach!==a)try{o(u,"forEach",a)}catch(l){u.forEach=a}}},"167b":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration -var e=t.defineLocale("oc-lnc",{months:{standalone:"genièr_febrièr_març_abril_mai_junh_julhet_agost_setembre_octòbre_novembre_decembre".split("_"),format:"de genièr_de febrièr_de març_d'abril_de mai_de junh_de julhet_d'agost_de setembre_d'octòbre_de novembre_de decembre".split("_"),isFormat:/D[oD]?(\s)+MMMM/},monthsShort:"gen._febr._març_abr._mai_junh_julh._ago._set._oct._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"dimenge_diluns_dimars_dimècres_dijòus_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dm._dc._dj._dv._ds.".split("_"),weekdaysMin:"dg_dl_dm_dc_dj_dv_ds".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [de] YYYY",ll:"D MMM YYYY",LLL:"D MMMM [de] YYYY [a] H:mm",lll:"D MMM YYYY, H:mm",LLLL:"dddd D MMMM [de] YYYY [a] H:mm",llll:"ddd D MMM YYYY, H:mm"},calendar:{sameDay:"[uèi a] LT",nextDay:"[deman a] LT",nextWeek:"dddd [a] LT",lastDay:"[ièr a] LT",lastWeek:"dddd [passat a] LT",sameElse:"L"},relativeTime:{future:"d'aquí %s",past:"fa %s",s:"unas segondas",ss:"%d segondas",m:"una minuta",mm:"%d minutas",h:"una ora",hh:"%d oras",d:"un jorn",dd:"%d jorns",M:"un mes",MM:"%d meses",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(r|n|t|è|a)/,ordinal:function(t,e){var n=1===t?"r":2===t?"n":3===t?"r":4===t?"t":"è";return"w"!==e&&"W"!==e||(n="a"),t+n},week:{dow:1,doy:4}});return e}))},"17c2":function(t,e,n){"use strict";var r=n("b727").forEach,i=n("a640"),a=n("ae40"),o=i("forEach"),s=a("forEach");t.exports=o&&s?[].forEach:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}},"19aa":function(t,e){t.exports=function(t,e,n){if(!(t instanceof e))throw TypeError("Incorrect "+(n?n+" ":"")+"invocation");return t}},"1b45":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; +var e=t.defineLocale("oc-lnc",{months:{standalone:"genièr_febrièr_març_abril_mai_junh_julhet_agost_setembre_octòbre_novembre_decembre".split("_"),format:"de genièr_de febrièr_de març_d'abril_de mai_de junh_de julhet_d'agost_de setembre_d'octòbre_de novembre_de decembre".split("_"),isFormat:/D[oD]?(\s)+MMMM/},monthsShort:"gen._febr._març_abr._mai_junh_julh._ago._set._oct._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"dimenge_diluns_dimars_dimècres_dijòus_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dm._dc._dj._dv._ds.".split("_"),weekdaysMin:"dg_dl_dm_dc_dj_dv_ds".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [de] YYYY",ll:"D MMM YYYY",LLL:"D MMMM [de] YYYY [a] H:mm",lll:"D MMM YYYY, H:mm",LLLL:"dddd D MMMM [de] YYYY [a] H:mm",llll:"ddd D MMM YYYY, H:mm"},calendar:{sameDay:"[uèi a] LT",nextDay:"[deman a] LT",nextWeek:"dddd [a] LT",lastDay:"[ièr a] LT",lastWeek:"dddd [passat a] LT",sameElse:"L"},relativeTime:{future:"d'aquí %s",past:"fa %s",s:"unas segondas",ss:"%d segondas",m:"una minuta",mm:"%d minutas",h:"una ora",hh:"%d oras",d:"un jorn",dd:"%d jorns",M:"un mes",MM:"%d meses",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(r|n|t|è|a)/,ordinal:function(t,e){var n=1===t?"r":2===t?"n":3===t?"r":4===t?"t":"è";return"w"!==e&&"W"!==e||(n="a"),t+n},week:{dow:1,doy:4}});return e}))},"17c2":function(t,e,n){"use strict";var r=n("b727").forEach,i=n("a640"),a=i("forEach");t.exports=a?[].forEach:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}},"19aa":function(t,e){t.exports=function(t,e,n){if(!(t instanceof e))throw TypeError("Incorrect "+(n?n+" ":"")+"invocation");return t}},"1b45":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration var e=t.defineLocale("mt",{months:"Jannar_Frar_Marzu_April_Mejju_Ġunju_Lulju_Awwissu_Settembru_Ottubru_Novembru_Diċembru".split("_"),monthsShort:"Jan_Fra_Mar_Apr_Mej_Ġun_Lul_Aww_Set_Ott_Nov_Diċ".split("_"),weekdays:"Il-Ħadd_It-Tnejn_It-Tlieta_L-Erbgħa_Il-Ħamis_Il-Ġimgħa_Is-Sibt".split("_"),weekdaysShort:"Ħad_Tne_Tli_Erb_Ħam_Ġim_Sib".split("_"),weekdaysMin:"Ħa_Tn_Tl_Er_Ħa_Ġi_Si".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Illum fil-]LT",nextDay:"[Għada fil-]LT",nextWeek:"dddd [fil-]LT",lastDay:"[Il-bieraħ fil-]LT",lastWeek:"dddd [li għadda] [fil-]LT",sameElse:"L"},relativeTime:{future:"f’ %s",past:"%s ilu",s:"ftit sekondi",ss:"%d sekondi",m:"minuta",mm:"%d minuti",h:"siegħa",hh:"%d siegħat",d:"ġurnata",dd:"%d ġranet",M:"xahar",MM:"%d xhur",y:"sena",yy:"%d sni"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}});return e}))},"1be4":function(t,e,n){var r=n("d066");t.exports=r("document","documentElement")},"1c0b":function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(String(t)+" is not a function");return t}},"1c7e":function(t,e,n){var r=n("b622"),i=r("iterator"),a=!1;try{var o=0,s={next:function(){return{done:!!o++}},return:function(){a=!0}};s[i]=function(){return this},Array.from(s,(function(){throw 2}))}catch(c){}t.exports=function(t,e){if(!e&&!a)return!1;var n=!1;try{var r={};r[i]=function(){return{next:function(){return{done:n=!0}}}},t(r)}catch(c){}return n}},"1cdc":function(t,e,n){var r=n("342f");t.exports=/(iphone|ipod|ipad).*applewebkit/i.test(r)},"1cfd":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration @@ -48,7 +48,7 @@ var e=t.defineLocale("ko",{months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_ //! moment.js locale configuration var e={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},n={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},r=["کانونی دووەم","شوبات","ئازار","نیسان","ئایار","حوزەیران","تەمموز","ئاب","ئەیلوول","تشرینی یەكەم","تشرینی دووەم","كانونی یەکەم"],i=t.defineLocale("ku",{months:r,monthsShort:r,weekdays:"یه‌كشه‌ممه‌_دووشه‌ممه‌_سێشه‌ممه‌_چوارشه‌ممه‌_پێنجشه‌ممه‌_هه‌ینی_شه‌ممه‌".split("_"),weekdaysShort:"یه‌كشه‌م_دووشه‌م_سێشه‌م_چوارشه‌م_پێنجشه‌م_هه‌ینی_شه‌ممه‌".split("_"),weekdaysMin:"ی_د_س_چ_پ_ه_ش".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/ئێواره‌|به‌یانی/,isPM:function(t){return/ئێواره‌/.test(t)},meridiem:function(t,e,n){return t<12?"به‌یانی":"ئێواره‌"},calendar:{sameDay:"[ئه‌مرۆ كاتژمێر] LT",nextDay:"[به‌یانی كاتژمێر] LT",nextWeek:"dddd [كاتژمێر] LT",lastDay:"[دوێنێ كاتژمێر] LT",lastWeek:"dddd [كاتژمێر] LT",sameElse:"L"},relativeTime:{future:"له‌ %s",past:"%s",s:"چه‌ند چركه‌یه‌ك",ss:"چركه‌ %d",m:"یه‌ك خوله‌ك",mm:"%d خوله‌ك",h:"یه‌ك كاتژمێر",hh:"%d كاتژمێر",d:"یه‌ك ڕۆژ",dd:"%d ڕۆژ",M:"یه‌ك مانگ",MM:"%d مانگ",y:"یه‌ك ساڵ",yy:"%d ساڵ"},preparse:function(t){return t.replace(/[١٢٣٤٥٦٧٨٩٠]/g,(function(t){return n[t]})).replace(/،/g,",")},postformat:function(t){return t.replace(/\d/g,(function(t){return e[t]})).replace(/,/g,"،")},week:{dow:6,doy:12}});return i}))},2444:function(t,e,n){"use strict";(function(e){var r=n("c532"),i=n("c8af"),a={"Content-Type":"application/x-www-form-urlencoded"};function o(t,e){!r.isUndefined(t)&&r.isUndefined(t["Content-Type"])&&(t["Content-Type"]=e)}function s(){var t;return("undefined"!==typeof XMLHttpRequest||"undefined"!==typeof e&&"[object process]"===Object.prototype.toString.call(e))&&(t=n("b50d")),t}var c={adapter:s(),transformRequest:[function(t,e){return i(e,"Accept"),i(e,"Content-Type"),r.isFormData(t)||r.isArrayBuffer(t)||r.isBuffer(t)||r.isStream(t)||r.isFile(t)||r.isBlob(t)?t:r.isArrayBufferView(t)?t.buffer:r.isURLSearchParams(t)?(o(e,"application/x-www-form-urlencoded;charset=utf-8"),t.toString()):r.isObject(t)?(o(e,"application/json;charset=utf-8"),JSON.stringify(t)):t}],transformResponse:[function(t){if("string"===typeof t)try{t=JSON.parse(t)}catch(e){}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(t){return t>=200&&t<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};r.forEach(["delete","get","head"],(function(t){c.headers[t]={}})),r.forEach(["post","put","patch"],(function(t){c.headers[t]=r.merge(a)})),t.exports=c}).call(this,n("4362"))},2532:function(t,e,n){"use strict";var r=n("23e7"),i=n("5a34"),a=n("1d80"),o=n("ab13");r({target:"String",proto:!0,forced:!o("includes")},{includes:function(t){return!!~String(a(this)).indexOf(i(t),arguments.length>1?arguments[1]:void 0)}})},2554:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration -function e(t,e,n){var r=t+" ";switch(n){case"ss":return r+=1===t?"sekunda":2===t||3===t||4===t?"sekunde":"sekundi",r;case"m":return e?"jedna minuta":"jedne minute";case"mm":return r+=1===t?"minuta":2===t||3===t||4===t?"minute":"minuta",r;case"h":return e?"jedan sat":"jednog sata";case"hh":return r+=1===t?"sat":2===t||3===t||4===t?"sata":"sati",r;case"dd":return r+=1===t?"dan":"dana",r;case"MM":return r+=1===t?"mjesec":2===t||3===t||4===t?"mjeseca":"mjeseci",r;case"yy":return r+=1===t?"godina":2===t||3===t||4===t?"godine":"godina",r}}var n=t.defineLocale("bs",{months:"januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",ss:e,m:e,mm:e,h:e,hh:e,d:"dan",dd:e,M:"mjesec",MM:e,y:"godinu",yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return n}))},"25f0":function(t,e,n){"use strict";var r=n("6eeb"),i=n("825a"),a=n("d039"),o=n("ad6d"),s="toString",c=RegExp.prototype,u=c[s],l=a((function(){return"/a/b"!=u.call({source:"a",flags:"b"})})),d=u.name!=s;(l||d)&&r(RegExp.prototype,s,(function(){var t=i(this),e=String(t.source),n=t.flags,r=String(void 0===n&&t instanceof RegExp&&!("flags"in c)?o.call(t):n);return"/"+e+"/"+r}),{unsafe:!0})},2626:function(t,e,n){"use strict";var r=n("d066"),i=n("9bf2"),a=n("b622"),o=n("83ab"),s=a("species");t.exports=function(t){var e=r(t),n=i.f;o&&e&&!e[s]&&n(e,s,{configurable:!0,get:function(){return this}})}},"26f9":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; +function e(t,e,n){var r=t+" ";switch(n){case"ss":return r+=1===t?"sekunda":2===t||3===t||4===t?"sekunde":"sekundi",r;case"m":return e?"jedna minuta":"jedne minute";case"mm":return r+=1===t?"minuta":2===t||3===t||4===t?"minute":"minuta",r;case"h":return e?"jedan sat":"jednog sata";case"hh":return r+=1===t?"sat":2===t||3===t||4===t?"sata":"sati",r;case"dd":return r+=1===t?"dan":"dana",r;case"MM":return r+=1===t?"mjesec":2===t||3===t||4===t?"mjeseca":"mjeseci",r;case"yy":return r+=1===t?"godina":2===t||3===t||4===t?"godine":"godina",r}}var n=t.defineLocale("bs",{months:"januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",ss:e,m:e,mm:e,h:e,hh:e,d:"dan",dd:e,M:"mjesec",MM:e,y:"godinu",yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return n}))},2626:function(t,e,n){"use strict";var r=n("d066"),i=n("9bf2"),a=n("b622"),o=n("83ab"),s=a("species");t.exports=function(t){var e=r(t),n=i.f;o&&e&&!e[s]&&n(e,s,{configurable:!0,get:function(){return this}})}},"26f9":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration var e={ss:"sekundė_sekundžių_sekundes",m:"minutė_minutės_minutę",mm:"minutės_minučių_minutes",h:"valanda_valandos_valandą",hh:"valandos_valandų_valandas",d:"diena_dienos_dieną",dd:"dienos_dienų_dienas",M:"mėnuo_mėnesio_mėnesį",MM:"mėnesiai_mėnesių_mėnesius",y:"metai_metų_metus",yy:"metai_metų_metus"};function n(t,e,n,r){return e?"kelios sekundės":r?"kelių sekundžių":"kelias sekundes"}function r(t,e,n,r){return e?a(n)[0]:r?a(n)[1]:a(n)[2]}function i(t){return t%10===0||t>10&&t<20}function a(t){return e[t].split("_")}function o(t,e,n,o){var s=t+" ";return 1===t?s+r(t,e,n[0],o):e?s+(i(t)?a(n)[1]:a(n)[0]):o?s+a(n)[1]:s+(i(t)?a(n)[1]:a(n)[2])}var s=t.defineLocale("lt",{months:{format:"sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio".split("_"),standalone:"sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis".split("_"),isFormat:/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|MMMM?(\[[^\[\]]*\]|\s)+D[oD]?/},monthsShort:"sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),weekdays:{format:"sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį".split("_"),standalone:"sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis".split("_"),isFormat:/dddd HH:mm/},weekdaysShort:"Sek_Pir_Ant_Tre_Ket_Pen_Šeš".split("_"),weekdaysMin:"S_P_A_T_K_Pn_Š".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY [m.] MMMM D [d.]",LLL:"YYYY [m.] MMMM D [d.], HH:mm [val.]",LLLL:"YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]",l:"YYYY-MM-DD",ll:"YYYY [m.] MMMM D [d.]",lll:"YYYY [m.] MMMM D [d.], HH:mm [val.]",llll:"YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]"},calendar:{sameDay:"[Šiandien] LT",nextDay:"[Rytoj] LT",nextWeek:"dddd LT",lastDay:"[Vakar] LT",lastWeek:"[Praėjusį] dddd LT",sameElse:"L"},relativeTime:{future:"po %s",past:"prieš %s",s:n,ss:o,m:r,mm:o,h:r,hh:o,d:r,dd:o,M:r,MM:o,y:r,yy:o},dayOfMonthOrdinalParse:/\d{1,2}-oji/,ordinal:function(t){return t+"-oji"},week:{dow:1,doy:4}});return s}))},2877:function(t,e,n){"use strict";function r(t,e,n,r,i,a,o,s){var c,u="function"===typeof t?t.options:t;if(e&&(u.render=e,u.staticRenderFns=n,u._compiled=!0),r&&(u.functional=!0),a&&(u._scopeId="data-v-"+a),o?(c=function(t){t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,t||"undefined"===typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),i&&i.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(o)},u._ssrRegister=c):i&&(c=s?function(){i.call(this,(u.functional?this.parent:this).$root.$options.shadowRoot)}:i),c)if(u.functional){u._injectStyles=c;var l=u.render;u.render=function(t,e){return c.call(e),l(t,e)}}else{var d=u.beforeCreate;u.beforeCreate=d?[].concat(d,c):[c]}return{exports:t,options:u}}n.d(e,"a",(function(){return r}))},2921:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration @@ -86,17 +86,17 @@ var e="leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen //! moment.js locale configuration var e={1:"௧",2:"௨",3:"௩",4:"௪",5:"௫",6:"௬",7:"௭",8:"௮",9:"௯",0:"௦"},n={"௧":"1","௨":"2","௩":"3","௪":"4","௫":"5","௬":"6","௭":"7","௮":"8","௯":"9","௦":"0"},r=t.defineLocale("ta",{months:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),monthsShort:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),weekdays:"ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை".split("_"),weekdaysShort:"ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி".split("_"),weekdaysMin:"ஞா_தி_செ_பு_வி_வெ_ச".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, HH:mm",LLLL:"dddd, D MMMM YYYY, HH:mm"},calendar:{sameDay:"[இன்று] LT",nextDay:"[நாளை] LT",nextWeek:"dddd, LT",lastDay:"[நேற்று] LT",lastWeek:"[கடந்த வாரம்] dddd, LT",sameElse:"L"},relativeTime:{future:"%s இல்",past:"%s முன்",s:"ஒரு சில விநாடிகள்",ss:"%d விநாடிகள்",m:"ஒரு நிமிடம்",mm:"%d நிமிடங்கள்",h:"ஒரு மணி நேரம்",hh:"%d மணி நேரம்",d:"ஒரு நாள்",dd:"%d நாட்கள்",M:"ஒரு மாதம்",MM:"%d மாதங்கள்",y:"ஒரு வருடம்",yy:"%d ஆண்டுகள்"},dayOfMonthOrdinalParse:/\d{1,2}வது/,ordinal:function(t){return t+"வது"},preparse:function(t){return t.replace(/[௧௨௩௪௫௬௭௮௯௦]/g,(function(t){return n[t]}))},postformat:function(t){return t.replace(/\d/g,(function(t){return e[t]}))},meridiemParse:/யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/,meridiem:function(t,e,n){return t<2?" யாமம்":t<6?" வைகறை":t<10?" காலை":t<14?" நண்பகல்":t<18?" எற்பாடு":t<22?" மாலை":" யாமம்"},meridiemHour:function(t,e){return 12===t&&(t=0),"யாமம்"===e?t<2?t:t+12:"வைகறை"===e||"காலை"===e||"நண்பகல்"===e&&t>=10?t:t+12},week:{dow:0,doy:6}});return r}))},"3e92":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration -var e={1:"೧",2:"೨",3:"೩",4:"೪",5:"೫",6:"೬",7:"೭",8:"೮",9:"೯",0:"೦"},n={"೧":"1","೨":"2","೩":"3","೪":"4","೫":"5","೬":"6","೭":"7","೮":"8","೯":"9","೦":"0"},r=t.defineLocale("kn",{months:"ಜನವರಿ_ಫೆಬ್ರವರಿ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂಬರ್_ಅಕ್ಟೋಬರ್_ನವೆಂಬರ್_ಡಿಸೆಂಬರ್".split("_"),monthsShort:"ಜನ_ಫೆಬ್ರ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂ_ಅಕ್ಟೋ_ನವೆಂ_ಡಿಸೆಂ".split("_"),monthsParseExact:!0,weekdays:"ಭಾನುವಾರ_ಸೋಮವಾರ_ಮಂಗಳವಾರ_ಬುಧವಾರ_ಗುರುವಾರ_ಶುಕ್ರವಾರ_ಶನಿವಾರ".split("_"),weekdaysShort:"ಭಾನು_ಸೋಮ_ಮಂಗಳ_ಬುಧ_ಗುರು_ಶುಕ್ರ_ಶನಿ".split("_"),weekdaysMin:"ಭಾ_ಸೋ_ಮಂ_ಬು_ಗು_ಶು_ಶ".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[ಇಂದು] LT",nextDay:"[ನಾಳೆ] LT",nextWeek:"dddd, LT",lastDay:"[ನಿನ್ನೆ] LT",lastWeek:"[ಕೊನೆಯ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ನಂತರ",past:"%s ಹಿಂದೆ",s:"ಕೆಲವು ಕ್ಷಣಗಳು",ss:"%d ಸೆಕೆಂಡುಗಳು",m:"ಒಂದು ನಿಮಿಷ",mm:"%d ನಿಮಿಷ",h:"ಒಂದು ಗಂಟೆ",hh:"%d ಗಂಟೆ",d:"ಒಂದು ದಿನ",dd:"%d ದಿನ",M:"ಒಂದು ತಿಂಗಳು",MM:"%d ತಿಂಗಳು",y:"ಒಂದು ವರ್ಷ",yy:"%d ವರ್ಷ"},preparse:function(t){return t.replace(/[೧೨೩೪೫೬೭೮೯೦]/g,(function(t){return n[t]}))},postformat:function(t){return t.replace(/\d/g,(function(t){return e[t]}))},meridiemParse:/ರಾತ್ರಿ|ಬೆಳಿಗ್ಗೆ|ಮಧ್ಯಾಹ್ನ|ಸಂಜೆ/,meridiemHour:function(t,e){return 12===t&&(t=0),"ರಾತ್ರಿ"===e?t<4?t:t+12:"ಬೆಳಿಗ್ಗೆ"===e?t:"ಮಧ್ಯಾಹ್ನ"===e?t>=10?t:t+12:"ಸಂಜೆ"===e?t+12:void 0},meridiem:function(t,e,n){return t<4?"ರಾತ್ರಿ":t<10?"ಬೆಳಿಗ್ಗೆ":t<17?"ಮಧ್ಯಾಹ್ನ":t<20?"ಸಂಜೆ":"ರಾತ್ರಿ"},dayOfMonthOrdinalParse:/\d{1,2}(ನೇ)/,ordinal:function(t){return t+"ನೇ"},week:{dow:0,doy:6}});return r}))},"3f8c":function(t,e){t.exports={}},4160:function(t,e,n){"use strict";var r=n("23e7"),i=n("17c2");r({target:"Array",proto:!0,forced:[].forEach!=i},{forEach:i})},"423e":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; +var e={1:"೧",2:"೨",3:"೩",4:"೪",5:"೫",6:"೬",7:"೭",8:"೮",9:"೯",0:"೦"},n={"೧":"1","೨":"2","೩":"3","೪":"4","೫":"5","೬":"6","೭":"7","೮":"8","೯":"9","೦":"0"},r=t.defineLocale("kn",{months:"ಜನವರಿ_ಫೆಬ್ರವರಿ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂಬರ್_ಅಕ್ಟೋಬರ್_ನವೆಂಬರ್_ಡಿಸೆಂಬರ್".split("_"),monthsShort:"ಜನ_ಫೆಬ್ರ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂ_ಅಕ್ಟೋ_ನವೆಂ_ಡಿಸೆಂ".split("_"),monthsParseExact:!0,weekdays:"ಭಾನುವಾರ_ಸೋಮವಾರ_ಮಂಗಳವಾರ_ಬುಧವಾರ_ಗುರುವಾರ_ಶುಕ್ರವಾರ_ಶನಿವಾರ".split("_"),weekdaysShort:"ಭಾನು_ಸೋಮ_ಮಂಗಳ_ಬುಧ_ಗುರು_ಶುಕ್ರ_ಶನಿ".split("_"),weekdaysMin:"ಭಾ_ಸೋ_ಮಂ_ಬು_ಗು_ಶು_ಶ".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[ಇಂದು] LT",nextDay:"[ನಾಳೆ] LT",nextWeek:"dddd, LT",lastDay:"[ನಿನ್ನೆ] LT",lastWeek:"[ಕೊನೆಯ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ನಂತರ",past:"%s ಹಿಂದೆ",s:"ಕೆಲವು ಕ್ಷಣಗಳು",ss:"%d ಸೆಕೆಂಡುಗಳು",m:"ಒಂದು ನಿಮಿಷ",mm:"%d ನಿಮಿಷ",h:"ಒಂದು ಗಂಟೆ",hh:"%d ಗಂಟೆ",d:"ಒಂದು ದಿನ",dd:"%d ದಿನ",M:"ಒಂದು ತಿಂಗಳು",MM:"%d ತಿಂಗಳು",y:"ಒಂದು ವರ್ಷ",yy:"%d ವರ್ಷ"},preparse:function(t){return t.replace(/[೧೨೩೪೫೬೭೮೯೦]/g,(function(t){return n[t]}))},postformat:function(t){return t.replace(/\d/g,(function(t){return e[t]}))},meridiemParse:/ರಾತ್ರಿ|ಬೆಳಿಗ್ಗೆ|ಮಧ್ಯಾಹ್ನ|ಸಂಜೆ/,meridiemHour:function(t,e){return 12===t&&(t=0),"ರಾತ್ರಿ"===e?t<4?t:t+12:"ಬೆಳಿಗ್ಗೆ"===e?t:"ಮಧ್ಯಾಹ್ನ"===e?t>=10?t:t+12:"ಸಂಜೆ"===e?t+12:void 0},meridiem:function(t,e,n){return t<4?"ರಾತ್ರಿ":t<10?"ಬೆಳಿಗ್ಗೆ":t<17?"ಮಧ್ಯಾಹ್ನ":t<20?"ಸಂಜೆ":"ರಾತ್ರಿ"},dayOfMonthOrdinalParse:/\d{1,2}(ನೇ)/,ordinal:function(t){return t+"ನೇ"},week:{dow:0,doy:6}});return r}))},"3f8c":function(t,e){t.exports={}},"423e":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration var e=t.defineLocale("ar-kw",{months:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),weekdays:"الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:0,doy:12}});return e}))},"428f":function(t,e,n){var r=n("da84");t.exports=r},4362:function(t,e,n){e.nextTick=function(t){var e=Array.prototype.slice.call(arguments);e.shift(),setTimeout((function(){t.apply(null,e)}),0)},e.platform=e.arch=e.execPath=e.title="browser",e.pid=1,e.browser=!0,e.env={},e.argv=[],e.binding=function(t){throw new Error("No such module. (Possibly not yet loaded)")},function(){var t,r="/";e.cwd=function(){return r},e.chdir=function(e){t||(t=n("df7c")),r=t.resolve(e,r)}}(),e.exit=e.kill=e.umask=e.dlopen=e.uptime=e.memoryUsage=e.uvCounters=function(){},e.features={}},"440c":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration function e(t,e,n,r){var i={m:["eng Minutt","enger Minutt"],h:["eng Stonn","enger Stonn"],d:["een Dag","engem Dag"],M:["ee Mount","engem Mount"],y:["ee Joer","engem Joer"]};return e?i[n][0]:i[n][1]}function n(t){var e=t.substr(0,t.indexOf(" "));return i(e)?"a "+t:"an "+t}function r(t){var e=t.substr(0,t.indexOf(" "));return i(e)?"viru "+t:"virun "+t}function i(t){if(t=parseInt(t,10),isNaN(t))return!1;if(t<0)return!0;if(t<10)return 4<=t&&t<=7;if(t<100){var e=t%10,n=t/10;return i(0===e?n:e)}if(t<1e4){while(t>=10)t/=10;return i(t)}return t/=1e3,i(t)}var a=t.defineLocale("lb",{months:"Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),weekdaysShort:"So._Mé._Dë._Më._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mé_Dë_Më_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm [Auer]",LTS:"H:mm:ss [Auer]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm [Auer]",LLLL:"dddd, D. MMMM YYYY H:mm [Auer]"},calendar:{sameDay:"[Haut um] LT",sameElse:"L",nextDay:"[Muer um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gëschter um] LT",lastWeek:function(){switch(this.day()){case 2:case 4:return"[Leschten] dddd [um] LT";default:return"[Leschte] dddd [um] LT"}}},relativeTime:{future:n,past:r,s:"e puer Sekonnen",ss:"%d Sekonnen",m:e,mm:"%d Minutten",h:e,hh:"%d Stonnen",d:e,dd:"%d Deeg",M:e,MM:"%d Méint",y:e,yy:"%d Joer"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return a}))},"44ad":function(t,e,n){var r=n("d039"),i=n("c6b6"),a="".split;t.exports=r((function(){return!Object("z").propertyIsEnumerable(0)}))?function(t){return"String"==i(t)?a.call(t,""):Object(t)}:Object},"44d2":function(t,e,n){var r=n("b622"),i=n("7c73"),a=n("9bf2"),o=r("unscopables"),s=Array.prototype;void 0==s[o]&&a.f(s,o,{configurable:!0,value:i(null)}),t.exports=function(t){s[o][t]=!0}},"44de":function(t,e,n){var r=n("da84");t.exports=function(t,e){var n=r.console;n&&n.error&&(1===arguments.length?n.error(t):n.error(t,e))}},"44e7":function(t,e,n){var r=n("861d"),i=n("c6b6"),a=n("b622"),o=a("match");t.exports=function(t){var e;return r(t)&&(void 0!==(e=t[o])?!!e:"RegExp"==i(t))}},"466d":function(t,e,n){"use strict";var r=n("d784"),i=n("825a"),a=n("50c4"),o=n("1d80"),s=n("8aa5"),c=n("14c3");r("match",1,(function(t,e,n){return[function(e){var n=o(this),r=void 0==e?void 0:e[t];return void 0!==r?r.call(e,n):new RegExp(e)[t](String(n))},function(t){var r=n(e,t,this);if(r.done)return r.value;var o=i(t),u=String(this);if(!o.global)return c(o,u);var l=o.unicode;o.lastIndex=0;var d,f=[],h=0;while(null!==(d=c(o,u))){var p=String(d[0]);f[h]=p,""===p&&(o.lastIndex=s(u,a(o.lastIndex),l)),h++}return 0===h?null:f}]}))},"467f":function(t,e,n){"use strict";var r=n("2d83");t.exports=function(t,e,n){var i=n.config.validateStatus;n.status&&i&&!i(n.status)?e(r("Request failed with status code "+n.status,n.config,null,n.request,n)):t(n)}},4840:function(t,e,n){var r=n("825a"),i=n("1c0b"),a=n("b622"),o=a("species");t.exports=function(t,e){var n,a=r(t).constructor;return void 0===a||void 0==(n=r(a)[o])?e:i(n)}},"485c":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration -var e={1:"-inci",5:"-inci",8:"-inci",70:"-inci",80:"-inci",2:"-nci",7:"-nci",20:"-nci",50:"-nci",3:"-üncü",4:"-üncü",100:"-üncü",6:"-ncı",9:"-uncu",10:"-uncu",30:"-uncu",60:"-ıncı",90:"-ıncı"},n=t.defineLocale("az",{months:"yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr".split("_"),monthsShort:"yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek".split("_"),weekdays:"Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə".split("_"),weekdaysShort:"Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən".split("_"),weekdaysMin:"Bz_BE_ÇA_Çə_CA_Cü_Şə".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[sabah saat] LT",nextWeek:"[gələn həftə] dddd [saat] LT",lastDay:"[dünən] LT",lastWeek:"[keçən həftə] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s əvvəl",s:"bir neçə saniyə",ss:"%d saniyə",m:"bir dəqiqə",mm:"%d dəqiqə",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir il",yy:"%d il"},meridiemParse:/gecə|səhər|gündüz|axşam/,isPM:function(t){return/^(gündüz|axşam)$/.test(t)},meridiem:function(t,e,n){return t<4?"gecə":t<12?"səhər":t<17?"gündüz":"axşam"},dayOfMonthOrdinalParse:/\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,ordinal:function(t){if(0===t)return t+"-ıncı";var n=t%10,r=t%100-n,i=t>=100?100:null;return t+(e[n]||e[r]||e[i])},week:{dow:1,doy:7}});return n}))},4930:function(t,e,n){var r=n("d039");t.exports=!!Object.getOwnPropertySymbols&&!r((function(){return!String(Symbol())}))},"493b":function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n("8c4e"),i=Object(r["a"])("$attrs","bvAttrs")},"49ab":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; +var e={1:"-inci",5:"-inci",8:"-inci",70:"-inci",80:"-inci",2:"-nci",7:"-nci",20:"-nci",50:"-nci",3:"-üncü",4:"-üncü",100:"-üncü",6:"-ncı",9:"-uncu",10:"-uncu",30:"-uncu",60:"-ıncı",90:"-ıncı"},n=t.defineLocale("az",{months:"yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr".split("_"),monthsShort:"yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek".split("_"),weekdays:"Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə".split("_"),weekdaysShort:"Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən".split("_"),weekdaysMin:"Bz_BE_ÇA_Çə_CA_Cü_Şə".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[sabah saat] LT",nextWeek:"[gələn həftə] dddd [saat] LT",lastDay:"[dünən] LT",lastWeek:"[keçən həftə] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s əvvəl",s:"bir neçə saniyə",ss:"%d saniyə",m:"bir dəqiqə",mm:"%d dəqiqə",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir il",yy:"%d il"},meridiemParse:/gecə|səhər|gündüz|axşam/,isPM:function(t){return/^(gündüz|axşam)$/.test(t)},meridiem:function(t,e,n){return t<4?"gecə":t<12?"səhər":t<17?"gündüz":"axşam"},dayOfMonthOrdinalParse:/\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,ordinal:function(t){if(0===t)return t+"-ıncı";var n=t%10,r=t%100-n,i=t>=100?100:null;return t+(e[n]||e[r]||e[i])},week:{dow:1,doy:7}});return n}))},4930:function(t,e,n){var r=n("605d"),i=n("2d00"),a=n("d039");t.exports=!!Object.getOwnPropertySymbols&&!a((function(){return!Symbol.sham&&(r?38===i:i>37&&i<41)}))},"493b":function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n("8c4e"),i=Object(r["a"])("$attrs","bvAttrs")},"49ab":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration var e=t.defineLocale("zh-hk",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日dddd HH:mm",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(t,e){return 12===t&&(t=0),"凌晨"===e||"早上"===e||"上午"===e?t:"中午"===e?t>=11?t:t+12:"下午"===e||"晚上"===e?t+12:void 0},meridiem:function(t,e,n){var r=100*t+e;return r<600?"凌晨":r<900?"早上":r<1200?"上午":1200===r?"中午":r<1800?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|週)/,ordinal:function(t,e){switch(e){case"d":case"D":case"DDD":return t+"日";case"M":return t+"月";case"w":case"W":return t+"週";default:return t}},relativeTime:{future:"%s後",past:"%s前",s:"幾秒",ss:"%d 秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}});return e}))},"4a38":function(t,e,n){"use strict";n.d(e,"f",(function(){return h})),n.d(e,"d",(function(){return p})),n.d(e,"e",(function(){return m})),n.d(e,"c",(function(){return b})),n.d(e,"b",(function(){return _})),n.d(e,"a",(function(){return v}));var r=n("992e"),i=n("906c"),a=n("7b1e"),o=n("d82f"),s=n("fa73"),c="a",u=function(t){return"%"+t.charCodeAt(0).toString(16)},l=function(t){return encodeURIComponent(Object(s["g"])(t)).replace(r["j"],u).replace(r["i"],",")},d=decodeURIComponent,f=function(t){if(!Object(a["k"])(t))return"";var e=Object(o["h"])(t).map((function(e){var n=t[e];return Object(a["o"])(n)?"":Object(a["g"])(n)?l(e):Object(a["a"])(n)?n.reduce((function(t,n){return Object(a["g"])(n)?t.push(l(e)):Object(a["o"])(n)||t.push(l(e)+"="+l(n)),t}),[]).join("&"):l(e)+"="+l(n)})).filter((function(t){return t.length>0})).join("&");return e?"?".concat(e):""},h=function(t){var e={};return t=Object(s["g"])(t).trim().replace(r["u"],""),t?(t.split("&").forEach((function(t){var n=t.replace(r["t"]," ").split("="),i=d(n.shift()),o=n.length>0?d(n.join("=")):null;Object(a["o"])(e[i])?e[i]=o:Object(a["a"])(e[i])?e[i].push(o):e[i]=[e[i],o]})),e):e},p=function(t){return!(!t.href&&!t.to)},m=function(t){return!(!t||Object(i["t"])(t,"a"))},b=function(t,e){var n=t.to,r=t.disabled,i=t.routerComponentName,a=!!e.$router;return!a||a&&(r||!n)?c:i||(e.$nuxt?"nuxt-link":"router-link")},_=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.target,n=t.rel;return"_blank"===e&&Object(a["g"])(n)?"noopener":n||null},v=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.href,n=t.to,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:c,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"#",o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"/";if(e)return e;if(m(r))return null;if(Object(a["n"])(n))return n||o;if(Object(a["k"])(n)&&(n.path||n.query||n.hash)){var u=Object(s["g"])(n.path),l=f(n.query),d=Object(s["g"])(n.hash);return d=d&&"#"!==d.charAt(0)?"#".concat(d):d,"".concat(u).concat(l).concat(d)||o}return i}},"4a7b":function(t,e,n){"use strict";var r=n("c532");t.exports=function(t,e){e=e||{};var n={},i=["url","method","data"],a=["headers","auth","proxy","params"],o=["baseURL","transformRequest","transformResponse","paramsSerializer","timeout","timeoutMessage","withCredentials","adapter","responseType","xsrfCookieName","xsrfHeaderName","onUploadProgress","onDownloadProgress","decompress","maxContentLength","maxBodyLength","maxRedirects","transport","httpAgent","httpsAgent","cancelToken","socketPath","responseEncoding"],s=["validateStatus"];function c(t,e){return r.isPlainObject(t)&&r.isPlainObject(e)?r.merge(t,e):r.isPlainObject(e)?r.merge({},e):r.isArray(e)?e.slice():e}function u(i){r.isUndefined(e[i])?r.isUndefined(t[i])||(n[i]=c(void 0,t[i])):n[i]=c(t[i],e[i])}r.forEach(i,(function(t){r.isUndefined(e[t])||(n[t]=c(void 0,e[t]))})),r.forEach(a,u),r.forEach(o,(function(i){r.isUndefined(e[i])?r.isUndefined(t[i])||(n[i]=c(void 0,t[i])):n[i]=c(void 0,e[i])})),r.forEach(s,(function(r){r in e?n[r]=c(t[r],e[r]):r in t&&(n[r]=c(void 0,t[r]))}));var l=i.concat(a).concat(o).concat(s),d=Object.keys(t).concat(Object.keys(e)).filter((function(t){return-1===l.indexOf(t)}));return r.forEach(d,u),n}},"4ba9":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration -function e(t,e,n){var r=t+" ";switch(n){case"ss":return r+=1===t?"sekunda":2===t||3===t||4===t?"sekunde":"sekundi",r;case"m":return e?"jedna minuta":"jedne minute";case"mm":return r+=1===t?"minuta":2===t||3===t||4===t?"minute":"minuta",r;case"h":return e?"jedan sat":"jednog sata";case"hh":return r+=1===t?"sat":2===t||3===t||4===t?"sata":"sati",r;case"dd":return r+=1===t?"dan":"dana",r;case"MM":return r+=1===t?"mjesec":2===t||3===t||4===t?"mjeseca":"mjeseci",r;case"yy":return r+=1===t?"godina":2===t||3===t||4===t?"godine":"godina",r}}var n=t.defineLocale("hr",{months:{format:"siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca".split("_"),standalone:"siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_")},monthsShort:"sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"Do MMMM YYYY",LLL:"Do MMMM YYYY H:mm",LLLL:"dddd, Do MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:return"[prošlu] [nedjelju] [u] LT";case 3:return"[prošlu] [srijedu] [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",ss:e,m:e,mm:e,h:e,hh:e,d:"dan",dd:e,M:"mjesec",MM:e,y:"godinu",yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return n}))},"4d64":function(t,e,n){var r=n("fc6a"),i=n("50c4"),a=n("23cb"),o=function(t){return function(e,n,o){var s,c=r(e),u=i(c.length),l=a(o,u);if(t&&n!=n){while(u>l)if(s=c[l++],s!=s)return!0}else for(;u>l;l++)if((t||l in c)&&c[l]===n)return t||l||0;return!t&&-1}};t.exports={includes:o(!0),indexOf:o(!1)}},"4de4":function(t,e,n){"use strict";var r=n("23e7"),i=n("b727").filter,a=n("1dde"),o=n("ae40"),s=a("filter"),c=o("filter");r({target:"Array",proto:!0,forced:!s||!c},{filter:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}})},"4df4":function(t,e,n){"use strict";var r=n("0366"),i=n("7b0b"),a=n("9bdd"),o=n("e95a"),s=n("50c4"),c=n("8418"),u=n("35a1");t.exports=function(t){var e,n,l,d,f,h,p=i(t),m="function"==typeof this?this:Array,b=arguments.length,_=b>1?arguments[1]:void 0,v=void 0!==_,y=u(p),g=0;if(v&&(_=r(_,b>2?arguments[2]:void 0,2)),void 0==y||m==Array&&o(y))for(e=s(p.length),n=new m(e);e>g;g++)h=v?_(p[g],g):p[g],c(n,g,h);else for(d=y.call(p),f=d.next,n=new m;!(l=f.call(d)).done;g++)h=v?a(d,_,[l.value,g],!0):l.value,c(n,g,h);return n.length=g,n}},5038:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; +function e(t,e,n){var r=t+" ";switch(n){case"ss":return r+=1===t?"sekunda":2===t||3===t||4===t?"sekunde":"sekundi",r;case"m":return e?"jedna minuta":"jedne minute";case"mm":return r+=1===t?"minuta":2===t||3===t||4===t?"minute":"minuta",r;case"h":return e?"jedan sat":"jednog sata";case"hh":return r+=1===t?"sat":2===t||3===t||4===t?"sata":"sati",r;case"dd":return r+=1===t?"dan":"dana",r;case"MM":return r+=1===t?"mjesec":2===t||3===t||4===t?"mjeseca":"mjeseci",r;case"yy":return r+=1===t?"godina":2===t||3===t||4===t?"godine":"godina",r}}var n=t.defineLocale("hr",{months:{format:"siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca".split("_"),standalone:"siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_")},monthsShort:"sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"Do MMMM YYYY",LLL:"Do MMMM YYYY H:mm",LLLL:"dddd, Do MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:return"[prošlu] [nedjelju] [u] LT";case 3:return"[prošlu] [srijedu] [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",ss:e,m:e,mm:e,h:e,hh:e,d:"dan",dd:e,M:"mjesec",MM:e,y:"godinu",yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return n}))},"4d64":function(t,e,n){var r=n("fc6a"),i=n("50c4"),a=n("23cb"),o=function(t){return function(e,n,o){var s,c=r(e),u=i(c.length),l=a(o,u);if(t&&n!=n){while(u>l)if(s=c[l++],s!=s)return!0}else for(;u>l;l++)if((t||l in c)&&c[l]===n)return t||l||0;return!t&&-1}};t.exports={includes:o(!0),indexOf:o(!1)}},"4de4":function(t,e,n){"use strict";var r=n("23e7"),i=n("b727").filter,a=n("1dde"),o=a("filter");r({target:"Array",proto:!0,forced:!o},{filter:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}})},"4df4":function(t,e,n){"use strict";var r=n("0366"),i=n("7b0b"),a=n("9bdd"),o=n("e95a"),s=n("50c4"),c=n("8418"),u=n("35a1");t.exports=function(t){var e,n,l,d,f,h,p=i(t),m="function"==typeof this?this:Array,b=arguments.length,_=b>1?arguments[1]:void 0,v=void 0!==_,y=u(p),g=0;if(v&&(_=r(_,b>2?arguments[2]:void 0,2)),void 0==y||m==Array&&o(y))for(e=s(p.length),n=new m(e);e>g;g++)h=v?_(p[g],g):p[g],c(n,g,h);else for(d=y.call(p),f=d.next,n=new m;!(l=f.call(d)).done;g++)h=v?a(d,_,[l.value,g],!0):l.value,c(n,g,h);return n.length=g,n}},5038:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration var e=t.defineLocale("id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Agt_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|siang|sore|malam/,meridiemHour:function(t,e){return 12===t&&(t=0),"pagi"===e?t:"siang"===e?t>=11?t:t+12:"sore"===e||"malam"===e?t+12:void 0},meridiem:function(t,e,n){return t<11?"pagi":t<15?"siang":t<19?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",ss:"%d detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:0,doy:6}});return e}))},"50c4":function(t,e,n){var r=n("a691"),i=Math.min;t.exports=function(t){return t>0?i(r(t),9007199254740991):0}},"50d3":function(t,e,n){"use strict";n.d(e,"b",(function(){return r})),n.d(e,"c",(function(){return i})),n.d(e,"a",(function(){return a}));var r="BvConfig",i="$bvConfig",a=["xs","sm","md","lg","xl"]},5120:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration @@ -106,7 +106,7 @@ var e=["جنوری","فروری","مارچ","اپریل","مئی","جون","جو //! moment.js locale configuration var e=t.defineLocale("ss",{months:"Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split("_"),monthsShort:"Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo".split("_"),weekdays:"Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo".split("_"),weekdaysShort:"Lis_Umb_Lsb_Les_Lsi_Lsh_Umg".split("_"),weekdaysMin:"Li_Us_Lb_Lt_Ls_Lh_Ug".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Namuhla nga] LT",nextDay:"[Kusasa nga] LT",nextWeek:"dddd [nga] LT",lastDay:"[Itolo nga] LT",lastWeek:"dddd [leliphelile] [nga] LT",sameElse:"L"},relativeTime:{future:"nga %s",past:"wenteka nga %s",s:"emizuzwana lomcane",ss:"%d mzuzwana",m:"umzuzu",mm:"%d emizuzu",h:"lihora",hh:"%d emahora",d:"lilanga",dd:"%d emalanga",M:"inyanga",MM:"%d tinyanga",y:"umnyaka",yy:"%d iminyaka"},meridiemParse:/ekuseni|emini|entsambama|ebusuku/,meridiem:function(t,e,n){return t<11?"ekuseni":t<15?"emini":t<19?"entsambama":"ebusuku"},meridiemHour:function(t,e){return 12===t&&(t=0),"ekuseni"===e?t:"emini"===e?t>=11?t:t+12:"entsambama"===e||"ebusuku"===e?0===t?0:t+12:void 0},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:"%d",week:{dow:1,doy:4}});return e}))},"55c9":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration -var e="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),n="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),r=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],i=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,a=t.defineLocale("es-us",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(t,r){return t?/-MMM-/.test(r)?n[t.month()]:e[t.month()]:e},monthsRegex:i,monthsShortRegex:i,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:r,longMonthsParse:r,shortMonthsParse:r,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"MM/DD/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY h:mm A",LLLL:"dddd, D [de] MMMM [de] YYYY h:mm A"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:0,doy:6}});return a}))},5692:function(t,e,n){var r=n("c430"),i=n("c6cd");(t.exports=function(t,e){return i[t]||(i[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.8.2",mode:r?"pure":"global",copyright:"© 2021 Denis Pushkarev (zloirock.ru)"})},"56ef":function(t,e,n){var r=n("d066"),i=n("241c"),a=n("7418"),o=n("825a");t.exports=r("Reflect","ownKeys")||function(t){var e=i.f(o(t)),n=a.f;return n?e.concat(n(t)):e}},"576c":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; +var e="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),n="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),r=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],i=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,a=t.defineLocale("es-us",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(t,r){return t?/-MMM-/.test(r)?n[t.month()]:e[t.month()]:e},monthsRegex:i,monthsShortRegex:i,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:r,longMonthsParse:r,shortMonthsParse:r,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"MM/DD/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY h:mm A",LLLL:"dddd, D [de] MMMM [de] YYYY h:mm A"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:0,doy:6}});return a}))},5692:function(t,e,n){var r=n("c430"),i=n("c6cd");(t.exports=function(t,e){return i[t]||(i[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.9.1",mode:r?"pure":"global",copyright:"© 2021 Denis Pushkarev (zloirock.ru)"})},"56ef":function(t,e,n){var r=n("d066"),i=n("241c"),a=n("7418"),o=n("825a");t.exports=r("Reflect","ownKeys")||function(t){var e=i.f(o(t)),n=a.f;return n?e.concat(n(t)):e}},"576c":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration var e=t.defineLocale("tet",{months:"Janeiru_Fevereiru_Marsu_Abril_Maiu_Juñu_Jullu_Agustu_Setembru_Outubru_Novembru_Dezembru".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingu_Segunda_Tersa_Kuarta_Kinta_Sesta_Sabadu".split("_"),weekdaysShort:"Dom_Seg_Ters_Kua_Kint_Sest_Sab".split("_"),weekdaysMin:"Do_Seg_Te_Ku_Ki_Ses_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Ohin iha] LT",nextDay:"[Aban iha] LT",nextWeek:"dddd [iha] LT",lastDay:"[Horiseik iha] LT",lastWeek:"dddd [semana kotuk] [iha] LT",sameElse:"L"},relativeTime:{future:"iha %s",past:"%s liuba",s:"segundu balun",ss:"segundu %d",m:"minutu ida",mm:"minutu %d",h:"oras ida",hh:"oras %d",d:"loron ida",dd:"loron %d",M:"fulan ida",MM:"fulan %d",y:"tinan ida",yy:"tinan %d"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(t){var e=t%10,n=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+n},week:{dow:1,doy:4}});return e}))},5899:function(t,e){t.exports="\t\n\v\f\r                 \u2028\u2029\ufeff"},"58a8":function(t,e,n){var r=n("1d80"),i=n("5899"),a="["+i+"]",o=RegExp("^"+a+a+"*"),s=RegExp(a+a+"*$"),c=function(t){return function(e){var n=String(r(e));return 1&t&&(n=n.replace(o,"")),2&t&&(n=n.replace(s,"")),n}};t.exports={start:c(1),end:c(2),trim:c(3)}},"58f2":function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n("a026"),i=n("0056"),a=n("a723"),o=n("cf75");function s(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var c=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=e.type,c=void 0===n?a["a"]:n,u=e.defaultValue,l=void 0===u?void 0:u,d=e.validator,f=void 0===d?void 0:d,h=e.event,p=void 0===h?i["y"]:h,m=s({},t,Object(o["c"])(c,l,f)),b=r["default"].extend({model:{prop:t,event:p},props:m});return{mixin:b,props:m,prop:t,event:p}}},"598a":function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration @@ -217,7 +217,7 @@ var e=t.defineLocale("bm",{months:"Zanwuyekalo_Fewuruyekalo_Marisikalo_Awirilika //! moment.js locale configuration function e(t,e,n,r){var i={s:["थोडया सॅकंडांनी","थोडे सॅकंड"],ss:[t+" सॅकंडांनी",t+" सॅकंड"],m:["एका मिणटान","एक मिनूट"],mm:[t+" मिणटांनी",t+" मिणटां"],h:["एका वरान","एक वर"],hh:[t+" वरांनी",t+" वरां"],d:["एका दिसान","एक दीस"],dd:[t+" दिसांनी",t+" दीस"],M:["एका म्हयन्यान","एक म्हयनो"],MM:[t+" म्हयन्यानी",t+" म्हयने"],y:["एका वर्सान","एक वर्स"],yy:[t+" वर्सांनी",t+" वर्सां"]};return r?i[n][0]:i[n][1]}var n=t.defineLocale("gom-deva",{months:{standalone:"जानेवारी_फेब्रुवारी_मार्च_एप्रील_मे_जून_जुलय_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर".split("_"),format:"जानेवारीच्या_फेब्रुवारीच्या_मार्चाच्या_एप्रीलाच्या_मेयाच्या_जूनाच्या_जुलयाच्या_ऑगस्टाच्या_सप्टेंबराच्या_ऑक्टोबराच्या_नोव्हेंबराच्या_डिसेंबराच्या".split("_"),isFormat:/MMMM(\s)+D[oD]?/},monthsShort:"जाने._फेब्रु._मार्च_एप्री._मे_जून_जुल._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.".split("_"),monthsParseExact:!0,weekdays:"आयतार_सोमार_मंगळार_बुधवार_बिरेस्तार_सुक्रार_शेनवार".split("_"),weekdaysShort:"आयत._सोम._मंगळ._बुध._ब्रेस्त._सुक्र._शेन.".split("_"),weekdaysMin:"आ_सो_मं_बु_ब्रे_सु_शे".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"A h:mm [वाजतां]",LTS:"A h:mm:ss [वाजतां]",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY A h:mm [वाजतां]",LLLL:"dddd, MMMM Do, YYYY, A h:mm [वाजतां]",llll:"ddd, D MMM YYYY, A h:mm [वाजतां]"},calendar:{sameDay:"[आयज] LT",nextDay:"[फाल्यां] LT",nextWeek:"[फुडलो] dddd[,] LT",lastDay:"[काल] LT",lastWeek:"[फाटलो] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%s",past:"%s आदीं",s:e,ss:e,m:e,mm:e,h:e,hh:e,d:e,dd:e,M:e,MM:e,y:e,yy:e},dayOfMonthOrdinalParse:/\d{1,2}(वेर)/,ordinal:function(t,e){switch(e){case"D":return t+"वेर";default:case"M":case"Q":case"DDD":case"d":case"w":case"W":return t}},week:{dow:0,doy:3},meridiemParse:/राती|सकाळीं|दनपारां|सांजे/,meridiemHour:function(t,e){return 12===t&&(t=0),"राती"===e?t<4?t:t+12:"सकाळीं"===e?t:"दनपारां"===e?t>12?t:t+12:"सांजे"===e?t+12:void 0},meridiem:function(t,e,n){return t<4?"राती":t<12?"सकाळीं":t<16?"दनपारां":t<20?"सांजे":"राती"}});return n}))},ab13:function(t,e,n){var r=n("b622"),i=r("match");t.exports=function(t){var e=/./;try{"/./"[t](e)}catch(n){try{return e[i]=!1,"/./"[t](e)}catch(r){}}return!1}},ac1f:function(t,e,n){"use strict";var r=n("23e7"),i=n("9263");r({target:"RegExp",proto:!0,forced:/./.exec!==i},{exec:i})},ad6d:function(t,e,n){"use strict";var r=n("825a");t.exports=function(){var t=r(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.dotAll&&(e+="s"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},ada2:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration -function e(t,e){var n=t.split("_");return e%10===1&&e%100!==11?n[0]:e%10>=2&&e%10<=4&&(e%100<10||e%100>=20)?n[1]:n[2]}function n(t,n,r){var i={ss:n?"секунда_секунди_секунд":"секунду_секунди_секунд",mm:n?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:n?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"};return"m"===r?n?"хвилина":"хвилину":"h"===r?n?"година":"годину":t+" "+e(i[r],+t)}function r(t,e){var n,r={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")};return!0===t?r["nominative"].slice(1,7).concat(r["nominative"].slice(0,1)):t?(n=/(\[[ВвУу]\]) ?dddd/.test(e)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(e)?"genitive":"nominative",r[n][t.day()]):r["nominative"]}function i(t){return function(){return t+"о"+(11===this.hours()?"б":"")+"] LT"}}var a=t.defineLocale("uk",{months:{format:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_"),standalone:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_")},monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:r,weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., HH:mm",LLLL:"dddd, D MMMM YYYY р., HH:mm"},calendar:{sameDay:i("[Сьогодні "),nextDay:i("[Завтра "),lastDay:i("[Вчора "),nextWeek:i("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return i("[Минулої] dddd [").call(this);case 1:case 2:case 4:return i("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",ss:n,m:n,mm:n,h:"годину",hh:n,d:"день",dd:n,M:"місяць",MM:n,y:"рік",yy:n},meridiemParse:/ночі|ранку|дня|вечора/,isPM:function(t){return/^(дня|вечора)$/.test(t)},meridiem:function(t,e,n){return t<4?"ночі":t<12?"ранку":t<17?"дня":"вечора"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го)/,ordinal:function(t,e){switch(e){case"M":case"d":case"DDD":case"w":case"W":return t+"-й";case"D":return t+"-го";default:return t}},week:{dow:1,doy:7}});return a}))},ae40:function(t,e,n){var r=n("83ab"),i=n("d039"),a=n("5135"),o=Object.defineProperty,s={},c=function(t){throw t};t.exports=function(t,e){if(a(s,t))return s[t];e||(e={});var n=[][t],u=!!a(e,"ACCESSORS")&&e.ACCESSORS,l=a(e,0)?e[0]:c,d=a(e,1)?e[1]:void 0;return s[t]=!!n&&!i((function(){if(u&&!r)return!0;var t={length:-1};u?o(t,1,{enumerable:!0,get:c}):t[1]=1,n.call(t,l,d)}))}},ae93:function(t,e,n){"use strict";var r,i,a,o=n("e163"),s=n("9112"),c=n("5135"),u=n("b622"),l=n("c430"),d=u("iterator"),f=!1,h=function(){return this};[].keys&&(a=[].keys(),"next"in a?(i=o(o(a)),i!==Object.prototype&&(r=i)):f=!0),void 0==r&&(r={}),l||c(r,d)||s(r,d,h),t.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:f}},b041:function(t,e,n){"use strict";var r=n("00ee"),i=n("f5df");t.exports=r?{}.toString:function(){return"[object "+i(this)+"]"}},b0c0:function(t,e,n){var r=n("83ab"),i=n("9bf2").f,a=Function.prototype,o=a.toString,s=/^\s*function ([^ (]*)/,c="name";r&&!(c in a)&&i(a,c,{configurable:!0,get:function(){try{return o.call(this).match(s)[1]}catch(t){return""}}})},b29d:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; +function e(t,e){var n=t.split("_");return e%10===1&&e%100!==11?n[0]:e%10>=2&&e%10<=4&&(e%100<10||e%100>=20)?n[1]:n[2]}function n(t,n,r){var i={ss:n?"секунда_секунди_секунд":"секунду_секунди_секунд",mm:n?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:n?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"};return"m"===r?n?"хвилина":"хвилину":"h"===r?n?"година":"годину":t+" "+e(i[r],+t)}function r(t,e){var n,r={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")};return!0===t?r["nominative"].slice(1,7).concat(r["nominative"].slice(0,1)):t?(n=/(\[[ВвУу]\]) ?dddd/.test(e)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(e)?"genitive":"nominative",r[n][t.day()]):r["nominative"]}function i(t){return function(){return t+"о"+(11===this.hours()?"б":"")+"] LT"}}var a=t.defineLocale("uk",{months:{format:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_"),standalone:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_")},monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:r,weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., HH:mm",LLLL:"dddd, D MMMM YYYY р., HH:mm"},calendar:{sameDay:i("[Сьогодні "),nextDay:i("[Завтра "),lastDay:i("[Вчора "),nextWeek:i("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return i("[Минулої] dddd [").call(this);case 1:case 2:case 4:return i("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",ss:n,m:n,mm:n,h:"годину",hh:n,d:"день",dd:n,M:"місяць",MM:n,y:"рік",yy:n},meridiemParse:/ночі|ранку|дня|вечора/,isPM:function(t){return/^(дня|вечора)$/.test(t)},meridiem:function(t,e,n){return t<4?"ночі":t<12?"ранку":t<17?"дня":"вечора"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го)/,ordinal:function(t,e){switch(e){case"M":case"d":case"DDD":case"w":case"W":return t+"-й";case"D":return t+"-го";default:return t}},week:{dow:1,doy:7}});return a}))},ae93:function(t,e,n){"use strict";var r,i,a,o=n("d039"),s=n("e163"),c=n("9112"),u=n("5135"),l=n("b622"),d=n("c430"),f=l("iterator"),h=!1,p=function(){return this};[].keys&&(a=[].keys(),"next"in a?(i=s(s(a)),i!==Object.prototype&&(r=i)):h=!0);var m=void 0==r||o((function(){var t={};return r[f].call(t)!==t}));m&&(r={}),d&&!m||u(r,f)||c(r,f,p),t.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:h}},b041:function(t,e,n){"use strict";var r=n("00ee"),i=n("f5df");t.exports=r?{}.toString:function(){return"[object "+i(this)+"]"}},b0c0:function(t,e,n){var r=n("83ab"),i=n("9bf2").f,a=Function.prototype,o=a.toString,s=/^\s*function ([^ (]*)/,c="name";r&&!(c in a)&&i(a,c,{configurable:!0,get:function(){try{return o.call(this).match(s)[1]}catch(t){return""}}})},b29d:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration var e=t.defineLocale("lo",{months:"ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ".split("_"),monthsShort:"ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ".split("_"),weekdays:"ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ".split("_"),weekdaysShort:"ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ".split("_"),weekdaysMin:"ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"ວັນdddd D MMMM YYYY HH:mm"},meridiemParse:/ຕອນເຊົ້າ|ຕອນແລງ/,isPM:function(t){return"ຕອນແລງ"===t},meridiem:function(t,e,n){return t<12?"ຕອນເຊົ້າ":"ຕອນແລງ"},calendar:{sameDay:"[ມື້ນີ້ເວລາ] LT",nextDay:"[ມື້ອື່ນເວລາ] LT",nextWeek:"[ວັນ]dddd[ໜ້າເວລາ] LT",lastDay:"[ມື້ວານນີ້ເວລາ] LT",lastWeek:"[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT",sameElse:"L"},relativeTime:{future:"ອີກ %s",past:"%sຜ່ານມາ",s:"ບໍ່ເທົ່າໃດວິນາທີ",ss:"%d ວິນາທີ",m:"1 ນາທີ",mm:"%d ນາທີ",h:"1 ຊົ່ວໂມງ",hh:"%d ຊົ່ວໂມງ",d:"1 ມື້",dd:"%d ມື້",M:"1 ເດືອນ",MM:"%d ເດືອນ",y:"1 ປີ",yy:"%d ປີ"},dayOfMonthOrdinalParse:/(ທີ່)\d{1,2}/,ordinal:function(t){return"ທີ່"+t}});return e}))},b3eb:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration @@ -229,11 +229,11 @@ var e=t.defineLocale("tzm-latn",{months:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_y //! moment.js locale configuration var e=t.defineLocale("jv",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des".split("_"),weekdays:"Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu".split("_"),weekdaysShort:"Min_Sen_Sel_Reb_Kem_Jem_Sep".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sp".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/enjing|siyang|sonten|ndalu/,meridiemHour:function(t,e){return 12===t&&(t=0),"enjing"===e?t:"siyang"===e?t>=11?t:t+12:"sonten"===e||"ndalu"===e?t+12:void 0},meridiem:function(t,e,n){return t<11?"enjing":t<15?"siyang":t<19?"sonten":"ndalu"},calendar:{sameDay:"[Dinten puniko pukul] LT",nextDay:"[Mbenjang pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kala wingi pukul] LT",lastWeek:"dddd [kepengker pukul] LT",sameElse:"L"},relativeTime:{future:"wonten ing %s",past:"%s ingkang kepengker",s:"sawetawis detik",ss:"%d detik",m:"setunggal menit",mm:"%d menit",h:"setunggal jam",hh:"%d jam",d:"sedinten",dd:"%d dinten",M:"sewulan",MM:"%d wulan",y:"setaun",yy:"%d taun"},week:{dow:1,doy:7}});return e}))},b575:function(t,e,n){var r,i,a,o,s,c,u,l,d=n("da84"),f=n("06cf").f,h=n("2cf4").set,p=n("1cdc"),m=n("a4b4"),b=n("605d"),_=d.MutationObserver||d.WebKitMutationObserver,v=d.document,y=d.process,g=d.Promise,O=f(d,"queueMicrotask"),j=O&&O.value;j||(r=function(){var t,e;b&&(t=y.domain)&&t.exit();while(i){e=i.fn,i=i.next;try{e()}catch(n){throw i?o():a=void 0,n}}a=void 0,t&&t.enter()},p||b||m||!_||!v?g&&g.resolve?(u=g.resolve(void 0),l=u.then,o=function(){l.call(u,r)}):o=b?function(){y.nextTick(r)}:function(){h.call(d,r)}:(s=!0,c=v.createTextNode(""),new _(r).observe(c,{characterData:!0}),o=function(){c.data=s=!s})),t.exports=j||function(t){var e={fn:t,next:void 0};a&&(a.next=e),i||(i=e,o()),a=e}},b5b7:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration -var e="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),n="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),r=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],i=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,a=t.defineLocale("es-mx",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(t,r){return t?/-MMM-/.test(r)?n[t.month()]:e[t.month()]:e},monthsRegex:i,monthsShortRegex:i,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:r,longMonthsParse:r,shortMonthsParse:r,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:0,doy:4},invalidDate:"Fecha inválida"});return a}))},b622:function(t,e,n){var r=n("da84"),i=n("5692"),a=n("5135"),o=n("90e3"),s=n("4930"),c=n("fdbf"),u=i("wks"),l=r.Symbol,d=c?l:l&&l.withoutSetter||o;t.exports=function(t){return a(u,t)||(s&&a(l,t)?u[t]=l[t]:u[t]=d("Symbol."+t)),u[t]}},b727:function(t,e,n){var r=n("0366"),i=n("44ad"),a=n("7b0b"),o=n("50c4"),s=n("65f0"),c=[].push,u=function(t){var e=1==t,n=2==t,u=3==t,l=4==t,d=6==t,f=7==t,h=5==t||d;return function(p,m,b,_){for(var v,y,g=a(p),O=i(g),j=r(m,b,3),w=o(O.length),M=0,L=_||s,k=e?L(p,w):n||f?L(p,0):void 0;w>M;M++)if((h||M in O)&&(v=O[M],y=j(v,M,g),t))if(e)k[M]=y;else if(y)switch(t){case 3:return!0;case 5:return v;case 6:return M;case 2:c.call(k,v)}else switch(t){case 4:return!1;case 7:c.call(k,v)}return d?-1:u||l?l:k}};t.exports={forEach:u(0),map:u(1),filter:u(2),some:u(3),every:u(4),find:u(5),findIndex:u(6),filterOut:u(7)}},b7e9:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; +var e="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),n="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),r=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],i=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,a=t.defineLocale("es-mx",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(t,r){return t?/-MMM-/.test(r)?n[t.month()]:e[t.month()]:e},monthsRegex:i,monthsShortRegex:i,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:r,longMonthsParse:r,shortMonthsParse:r,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:0,doy:4},invalidDate:"Fecha inválida"});return a}))},b622:function(t,e,n){var r=n("da84"),i=n("5692"),a=n("5135"),o=n("90e3"),s=n("4930"),c=n("fdbf"),u=i("wks"),l=r.Symbol,d=c?l:l&&l.withoutSetter||o;t.exports=function(t){return a(u,t)&&(s||"string"==typeof u[t])||(s&&a(l,t)?u[t]=l[t]:u[t]=d("Symbol."+t)),u[t]}},b727:function(t,e,n){var r=n("0366"),i=n("44ad"),a=n("7b0b"),o=n("50c4"),s=n("65f0"),c=[].push,u=function(t){var e=1==t,n=2==t,u=3==t,l=4==t,d=6==t,f=7==t,h=5==t||d;return function(p,m,b,_){for(var v,y,g=a(p),O=i(g),j=r(m,b,3),w=o(O.length),M=0,L=_||s,k=e?L(p,w):n||f?L(p,0):void 0;w>M;M++)if((h||M in O)&&(v=O[M],y=j(v,M,g),t))if(e)k[M]=y;else if(y)switch(t){case 3:return!0;case 5:return v;case 6:return M;case 2:c.call(k,v)}else switch(t){case 4:return!1;case 7:c.call(k,v)}return d?-1:u||l?l:k}};t.exports={forEach:u(0),map:u(1),filter:u(2),some:u(3),every:u(4),find:u(5),findIndex:u(6),filterOut:u(7)}},b7e9:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration var e=t.defineLocale("en-sg",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},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"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(t){var e=t%10,n=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+n},week:{dow:1,doy:4}});return e}))},b84c:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration -var e=t.defineLocale("nn",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_apr._mai_juni_juli_aug._sep._okt._nov._des.".split("_"),monthsParseExact:!0,weekdays:"sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),weekdaysShort:"su._må._ty._on._to._fr._lau.".split("_"),weekdaysMin:"su_må_ty_on_to_fr_la".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[I dag klokka] LT",nextDay:"[I morgon klokka] LT",nextWeek:"dddd [klokka] LT",lastDay:"[I går klokka] LT",lastWeek:"[Føregåande] dddd [klokka] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s sidan",s:"nokre sekund",ss:"%d sekund",m:"eit minutt",mm:"%d minutt",h:"ein time",hh:"%d timar",d:"ein dag",dd:"%d dagar",w:"ei veke",ww:"%d veker",M:"ein månad",MM:"%d månader",y:"eit år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return e}))},b85c:function(t,e,n){"use strict";n.d(e,"a",(function(){return a}));n("a4d3"),n("e01a"),n("d28b"),n("d3b7"),n("3ca3"),n("ddb0"),n("a630"),n("fb6a"),n("b0c0"),n("25f0");function r(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,c=!1;return{s:function(){n=t[Symbol.iterator]()},n:function(){var t=n.next();return s=t.done,t},e:function(t){c=!0,o=t},f:function(){try{s||null==n["return"]||n["return"]()}finally{if(c)throw o}}}}},b97c:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; +var e=t.defineLocale("nn",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_apr._mai_juni_juli_aug._sep._okt._nov._des.".split("_"),monthsParseExact:!0,weekdays:"sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),weekdaysShort:"su._må._ty._on._to._fr._lau.".split("_"),weekdaysMin:"su_må_ty_on_to_fr_la".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[I dag klokka] LT",nextDay:"[I morgon klokka] LT",nextWeek:"dddd [klokka] LT",lastDay:"[I går klokka] LT",lastWeek:"[Føregåande] dddd [klokka] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s sidan",s:"nokre sekund",ss:"%d sekund",m:"eit minutt",mm:"%d minutt",h:"ein time",hh:"%d timar",d:"ein dag",dd:"%d dagar",w:"ei veke",ww:"%d veker",M:"ein månad",MM:"%d månader",y:"eit år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return e}))},b85c:function(t,e,n){"use strict";n.d(e,"a",(function(){return a}));n("a4d3"),n("e01a"),n("d3b7"),n("d28b"),n("3ca3"),n("ddb0"),n("fb6a"),n("b0c0"),n("a630");function r(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,c=!1;return{s:function(){n=t[Symbol.iterator]()},n:function(){var t=n.next();return s=t.done,t},e:function(t){c=!0,o=t},f:function(){try{s||null==n["return"]||n["return"]()}finally{if(c)throw o}}}}},b97c:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration var e={ss:"sekundes_sekundēm_sekunde_sekundes".split("_"),m:"minūtes_minūtēm_minūte_minūtes".split("_"),mm:"minūtes_minūtēm_minūte_minūtes".split("_"),h:"stundas_stundām_stunda_stundas".split("_"),hh:"stundas_stundām_stunda_stundas".split("_"),d:"dienas_dienām_diena_dienas".split("_"),dd:"dienas_dienām_diena_dienas".split("_"),M:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),MM:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),y:"gada_gadiem_gads_gadi".split("_"),yy:"gada_gadiem_gads_gadi".split("_")};function n(t,e,n){return n?e%10===1&&e%100!==11?t[2]:t[3]:e%10===1&&e%100!==11?t[0]:t[1]}function r(t,r,i){return t+" "+n(e[i],t,r)}function i(t,r,i){return n(e[i],t,r)}function a(t,e){return e?"dažas sekundes":"dažām sekundēm"}var o=t.defineLocale("lv",{months:"janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"),weekdays:"svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY.",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, HH:mm",LLLL:"YYYY. [gada] D. MMMM, dddd, HH:mm"},calendar:{sameDay:"[Šodien pulksten] LT",nextDay:"[Rīt pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pagājušā] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"pēc %s",past:"pirms %s",s:a,ss:r,m:i,mm:r,h:i,hh:r,d:i,dd:r,M:i,MM:r,y:i,yy:r},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return o}))},bb71:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration @@ -250,7 +250,7 @@ a.version="2.29.1",o(Kn),a.fn=ua,a.min=tr,a.max=er,a.now=nr,a.utc=b,a.unix=la,a. //! moment.js locale configuration var e=t.defineLocale("he",{months:"ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"),monthsShort:"ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"),weekdays:"ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"),weekdaysShort:"א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),weekdaysMin:"א_ב_ג_ד_ה_ו_ש".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [ב]MMMM YYYY",LLL:"D [ב]MMMM YYYY HH:mm",LLLL:"dddd, D [ב]MMMM YYYY HH:mm",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[היום ב־]LT",nextDay:"[מחר ב־]LT",nextWeek:"dddd [בשעה] LT",lastDay:"[אתמול ב־]LT",lastWeek:"[ביום] dddd [האחרון בשעה] LT",sameElse:"L"},relativeTime:{future:"בעוד %s",past:"לפני %s",s:"מספר שניות",ss:"%d שניות",m:"דקה",mm:"%d דקות",h:"שעה",hh:function(t){return 2===t?"שעתיים":t+" שעות"},d:"יום",dd:function(t){return 2===t?"יומיים":t+" ימים"},M:"חודש",MM:function(t){return 2===t?"חודשיים":t+" חודשים"},y:"שנה",yy:function(t){return 2===t?"שנתיים":t%10===0&&10!==t?t+" שנה":t+" שנים"}},meridiemParse:/אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,isPM:function(t){return/^(אחה"צ|אחרי הצהריים|בערב)$/.test(t)},meridiem:function(t,e,n){return t<5?"לפנות בוקר":t<10?"בבוקר":t<12?n?'לפנה"צ':"לפני הצהריים":t<18?n?'אחה"צ':"אחרי הצהריים":"בערב"}});return e}))},c8af:function(t,e,n){"use strict";var r=n("c532");t.exports=function(t,e){r.forEach(t,(function(n,r){r!==e&&r.toUpperCase()===e.toUpperCase()&&(t[e]=n,delete t[r])}))}},c8ba:function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(r){"object"===typeof window&&(n=window)}t.exports=n},c8f3:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration -var e=t.defineLocale("sq",{months:"Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"),monthsShort:"Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"),weekdays:"E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë".split("_"),weekdaysShort:"Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"),weekdaysMin:"D_H_Ma_Më_E_P_Sh".split("_"),weekdaysParseExact:!0,meridiemParse:/PD|MD/,isPM:function(t){return"M"===t.charAt(0)},meridiem:function(t,e,n){return t<12?"PD":"MD"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Sot në] LT",nextDay:"[Nesër në] LT",nextWeek:"dddd [në] LT",lastDay:"[Dje në] LT",lastWeek:"dddd [e kaluar në] LT",sameElse:"L"},relativeTime:{future:"në %s",past:"%s më parë",s:"disa sekonda",ss:"%d sekonda",m:"një minutë",mm:"%d minuta",h:"një orë",hh:"%d orë",d:"një ditë",dd:"%d ditë",M:"një muaj",MM:"%d muaj",y:"një vit",yy:"%d vite"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return e}))},c9a9:function(t,e,n){"use strict";n.d(e,"a",(function(){return p}));var r=n("7b1e"),i=n("d82f");function a(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function o(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,r=new Array(e);n1&&void 0!==arguments[1]?arguments[1]:e;return Object(r["a"])(e)?e.reduce((function(e,n){return[].concat(c(e),[t(n,n)])}),[]):Object(r["k"])(e)?Object(i["h"])(e).reduce((function(n,r){return o(o({},n),{},s({},r,t(e[r],e[r])))}),{}):n}},ca84:function(t,e,n){var r=n("5135"),i=n("fc6a"),a=n("4d64").indexOf,o=n("d012");t.exports=function(t,e){var n,s=i(t),c=0,u=[];for(n in s)!r(o,n)&&r(s,n)&&u.push(n);while(e.length>c)r(s,n=e[c++])&&(~a(u,n)||u.push(n));return u}},ca88:function(t,e,n){"use strict";n.d(e,"a",(function(){return b})),n.d(e,"c",(function(){return _})),n.d(e,"d",(function(){return v})),n.d(e,"b",(function(){return y}));var r=n("e863");function i(t){return i="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"===typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i(t)}function a(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){if("function"!==typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&p(t,e)}function s(t){var e=f();return function(){var n,r=m(t);if(e){var i=m(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return c(this,n)}}function c(t,e){return!e||"object"!==i(e)&&"function"!==typeof e?u(t):e}function u(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function l(t){var e="function"===typeof Map?new Map:void 0;return l=function(t){if(null===t||!h(t))return t;if("function"!==typeof t)throw new TypeError("Super expression must either be null or a function");if("undefined"!==typeof e){if(e.has(t))return e.get(t);e.set(t,n)}function n(){return d(t,arguments,m(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),p(n,t)},l(t)}function d(t,e,n){return d=f()?Reflect.construct:function(t,e,n){var r=[null];r.push.apply(r,e);var i=Function.bind.apply(t,r),a=new i;return n&&p(a,n.prototype),a},d.apply(null,arguments)}function f(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}function h(t){return-1!==Function.toString.call(t).indexOf("[native code]")}function p(t,e){return p=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},p(t,e)}function m(t){return m=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},m(t)}var b=r["h"]?r["k"].Element:function(t){o(n,t);var e=s(n);function n(){return a(this,n),e.apply(this,arguments)}return n}(l(Object)),_=r["h"]?r["k"].HTMLElement:function(t){o(n,t);var e=s(n);function n(){return a(this,n),e.apply(this,arguments)}return n}(b),v=r["h"]?r["k"].SVGElement:function(t){o(n,t);var e=s(n);function n(){return a(this,n),e.apply(this,arguments)}return n}(b),y=r["h"]?r["k"].File:function(t){o(n,t);var e=s(n);function n(){return a(this,n),e.apply(this,arguments)}return n}(l(Object))},caad:function(t,e,n){"use strict";var r=n("23e7"),i=n("4d64").includes,a=n("44d2"),o=n("ae40"),s=o("indexOf",{ACCESSORS:!0,1:0});r({target:"Array",proto:!0,forced:!s},{includes:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}}),a("includes")},cc12:function(t,e,n){var r=n("da84"),i=n("861d"),a=r.document,o=i(a)&&i(a.createElement);t.exports=function(t){return o?a.createElement(t):{}}},cca6:function(t,e,n){var r=n("23e7"),i=n("60da");r({target:"Object",stat:!0,forced:Object.assign!==i},{assign:i})},cdf9:function(t,e,n){var r=n("825a"),i=n("861d"),a=n("f069");t.exports=function(t,e){if(r(t),i(e)&&e.constructor===t)return e;var n=a.f(t),o=n.resolve;return o(e),n.promise}},ce2a:function(t,e,n){"use strict";n.d(e,"a",(function(){return m}));var r=n("a026"),i=n("b42e"),a=n("c637"),o=n("a723"),s=n("7b1e"),c=n("cf75");function u(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function l(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,r=new Array(e);n1&&void 0!==arguments[1]?arguments[1]:e;return Object(r["a"])(e)?e.reduce((function(e,n){return[].concat(c(e),[t(n,n)])}),[]):Object(r["k"])(e)?Object(i["h"])(e).reduce((function(n,r){return o(o({},n),{},s({},r,t(e[r],e[r])))}),{}):n}},ca84:function(t,e,n){var r=n("5135"),i=n("fc6a"),a=n("4d64").indexOf,o=n("d012");t.exports=function(t,e){var n,s=i(t),c=0,u=[];for(n in s)!r(o,n)&&r(s,n)&&u.push(n);while(e.length>c)r(s,n=e[c++])&&(~a(u,n)||u.push(n));return u}},ca88:function(t,e,n){"use strict";n.d(e,"a",(function(){return b})),n.d(e,"c",(function(){return _})),n.d(e,"d",(function(){return v})),n.d(e,"b",(function(){return y}));var r=n("e863");function i(t){return i="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"===typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i(t)}function a(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){if("function"!==typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&p(t,e)}function s(t){var e=f();return function(){var n,r=m(t);if(e){var i=m(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return c(this,n)}}function c(t,e){return!e||"object"!==i(e)&&"function"!==typeof e?u(t):e}function u(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function l(t){var e="function"===typeof Map?new Map:void 0;return l=function(t){if(null===t||!h(t))return t;if("function"!==typeof t)throw new TypeError("Super expression must either be null or a function");if("undefined"!==typeof e){if(e.has(t))return e.get(t);e.set(t,n)}function n(){return d(t,arguments,m(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),p(n,t)},l(t)}function d(t,e,n){return d=f()?Reflect.construct:function(t,e,n){var r=[null];r.push.apply(r,e);var i=Function.bind.apply(t,r),a=new i;return n&&p(a,n.prototype),a},d.apply(null,arguments)}function f(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}function h(t){return-1!==Function.toString.call(t).indexOf("[native code]")}function p(t,e){return p=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},p(t,e)}function m(t){return m=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},m(t)}var b=r["h"]?r["k"].Element:function(t){o(n,t);var e=s(n);function n(){return a(this,n),e.apply(this,arguments)}return n}(l(Object)),_=r["h"]?r["k"].HTMLElement:function(t){o(n,t);var e=s(n);function n(){return a(this,n),e.apply(this,arguments)}return n}(b),v=r["h"]?r["k"].SVGElement:function(t){o(n,t);var e=s(n);function n(){return a(this,n),e.apply(this,arguments)}return n}(b),y=r["h"]?r["k"].File:function(t){o(n,t);var e=s(n);function n(){return a(this,n),e.apply(this,arguments)}return n}(l(Object))},caad:function(t,e,n){"use strict";var r=n("23e7"),i=n("4d64").includes,a=n("44d2");r({target:"Array",proto:!0},{includes:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}}),a("includes")},cc12:function(t,e,n){var r=n("da84"),i=n("861d"),a=r.document,o=i(a)&&i(a.createElement);t.exports=function(t){return o?a.createElement(t):{}}},cca6:function(t,e,n){var r=n("23e7"),i=n("60da");r({target:"Object",stat:!0,forced:Object.assign!==i},{assign:i})},cdf9:function(t,e,n){var r=n("825a"),i=n("861d"),a=n("f069");t.exports=function(t,e){if(r(t),i(e)&&e.constructor===t)return e;var n=a.f(t),o=n.resolve;return o(e),n.promise}},ce2a:function(t,e,n){"use strict";n.d(e,"a",(function(){return m}));var r=n("a026"),i=n("b42e"),a=n("c637"),o=n("a723"),s=n("7b1e"),c=n("cf75");function u(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function l(t){for(var e=1;e=2&&t<=4?e[1]:e[2]},translate:function(t,n,r){var i=e.words[r];return 1===r.length?n?i[0]:i[1]:t+" "+e.correctGrammaticalCase(t,i)}},n=t.defineLocale("sr",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sre._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D. M. YYYY.",LL:"D. MMMM YYYY.",LLL:"D. MMMM YYYY. H:mm",LLLL:"dddd, D. MMMM YYYY. H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){var t=["[prošle] [nedelje] [u] LT","[prošlog] [ponedeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"];return t[this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"nekoliko sekundi",ss:e.translate,m:e.translate,mm:e.translate,h:e.translate,hh:e.translate,d:"dan",dd:e.translate,M:"mesec",MM:e.translate,y:"godinu",yy:e.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}});return n}))},cf51:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration @@ -319,7 +319,7 @@ var e={1:"੧",2:"੨",3:"੩",4:"੪",5:"੫",6:"੬",7:"੭",8:"੮",9:"੯",0 //! moment.js locale configuration var e=["Am Faoilleach","An Gearran","Am Màrt","An Giblean","An Cèitean","An t-Ògmhios","An t-Iuchar","An Lùnastal","An t-Sultain","An Dàmhair","An t-Samhain","An Dùbhlachd"],n=["Faoi","Gear","Màrt","Gibl","Cèit","Ògmh","Iuch","Lùn","Sult","Dàmh","Samh","Dùbh"],r=["Didòmhnaich","Diluain","Dimàirt","Diciadain","Diardaoin","Dihaoine","Disathairne"],i=["Did","Dil","Dim","Dic","Dia","Dih","Dis"],a=["Dò","Lu","Mà","Ci","Ar","Ha","Sa"],o=t.defineLocale("gd",{months:e,monthsShort:n,monthsParseExact:!0,weekdays:r,weekdaysShort:i,weekdaysMin:a,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[An-diugh aig] LT",nextDay:"[A-màireach aig] LT",nextWeek:"dddd [aig] LT",lastDay:"[An-dè aig] LT",lastWeek:"dddd [seo chaidh] [aig] LT",sameElse:"L"},relativeTime:{future:"ann an %s",past:"bho chionn %s",s:"beagan diogan",ss:"%d diogan",m:"mionaid",mm:"%d mionaidean",h:"uair",hh:"%d uairean",d:"latha",dd:"%d latha",M:"mìos",MM:"%d mìosan",y:"bliadhna",yy:"%d bliadhna"},dayOfMonthOrdinalParse:/\d{1,2}(d|na|mh)/,ordinal:function(t){var e=1===t?"d":t%10===2?"na":"mh";return t+e},week:{dow:1,doy:4}});return o}))},f6b49:function(t,e,n){"use strict";var r=n("c532");function i(){this.handlers=[]}i.prototype.use=function(t,e){return this.handlers.push({fulfilled:t,rejected:e}),this.handlers.length-1},i.prototype.eject=function(t){this.handlers[t]&&(this.handlers[t]=null)},i.prototype.forEach=function(t){r.forEach(this.handlers,(function(e){null!==e&&t(e)}))},t.exports=i},f772:function(t,e,n){var r=n("5692"),i=n("90e3"),a=r("keys");t.exports=function(t){return a[t]||(a[t]=i(t))}},fa73:function(t,e,n){"use strict";n.d(e,"b",(function(){return a})),n.d(e,"e",(function(){return o})),n.d(e,"f",(function(){return s})),n.d(e,"d",(function(){return c})),n.d(e,"j",(function(){return u})),n.d(e,"a",(function(){return l})),n.d(e,"g",(function(){return d})),n.d(e,"i",(function(){return f})),n.d(e,"h",(function(){return h})),n.d(e,"c",(function(){return p}));var r=n("992e"),i=n("7b1e"),a=function(t){return t.replace(r["p"],"-$1").toLowerCase()},o=function(t){return t=a(t).replace(r["F"],(function(t,e){return e?e.toUpperCase():""})),t.charAt(0).toUpperCase()+t.slice(1)},s=function(t){return t.replace(r["E"]," ").replace(r["r"],(function(t,e,n){return e+" "+n})).replace(r["z"],(function(t,e,n){return e+n.toUpperCase()}))},c=function(t){return t=Object(i["n"])(t)?t.trim():String(t),t.charAt(0).toLowerCase()+t.slice(1)},u=function(t){return t=Object(i["n"])(t)?t.trim():String(t),t.charAt(0).toUpperCase()+t.slice(1)},l=function(t){return t.replace(r["v"],"\\$&")},d=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;return Object(i["p"])(t)?"":Object(i["a"])(t)||Object(i["k"])(t)&&t.toString===Object.prototype.toString?JSON.stringify(t,null,e):String(t)},f=function(t){return d(t).replace(r["C"],"")},h=function(t){return d(t).trim()},p=function(t){return d(t).toLowerCase()}},facd:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration -var e="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),n="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),r=[/^jan/i,/^feb/i,/^maart|mrt.?$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],i=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,a=t.defineLocale("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(t,r){return t?/-MMM-/.test(r)?n[t.month()]:e[t.month()]:e},monthsRegex:i,monthsShortRegex:i,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:r,longMonthsParse:r,shortMonthsParse:r,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",w:"één week",ww:"%d weken",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(t){return t+(1===t||8===t||t>=20?"ste":"de")},week:{dow:1,doy:4}});return a}))},fb6a:function(t,e,n){"use strict";var r=n("23e7"),i=n("861d"),a=n("e8b5"),o=n("23cb"),s=n("50c4"),c=n("fc6a"),u=n("8418"),l=n("b622"),d=n("1dde"),f=n("ae40"),h=d("slice"),p=f("slice",{ACCESSORS:!0,0:0,1:2}),m=l("species"),b=[].slice,_=Math.max;r({target:"Array",proto:!0,forced:!h||!p},{slice:function(t,e){var n,r,l,d=c(this),f=s(d.length),h=o(t,f),p=o(void 0===e?f:e,f);if(a(d)&&(n=d.constructor,"function"!=typeof n||n!==Array&&!a(n.prototype)?i(n)&&(n=n[m],null===n&&(n=void 0)):n=void 0,n===Array||void 0===n))return b.call(d,h,p);for(r=new(void 0===n?Array:n)(_(p-h,0)),l=0;h=20?"ste":"de")},week:{dow:1,doy:4}});return a}))},fb6a:function(t,e,n){"use strict";var r=n("23e7"),i=n("861d"),a=n("e8b5"),o=n("23cb"),s=n("50c4"),c=n("fc6a"),u=n("8418"),l=n("b622"),d=n("1dde"),f=d("slice"),h=l("species"),p=[].slice,m=Math.max;r({target:"Array",proto:!0,forced:!f},{slice:function(t,e){var n,r,l,d=c(this),f=s(d.length),b=o(t,f),_=o(void 0===e?f:e,f);if(a(d)&&(n=d.constructor,"function"!=typeof n||n!==Array&&!a(n.prototype)?i(n)&&(n=n[h],null===n&&(n=void 0)):n=void 0,n===Array||void 0===n))return p.call(d,b,_);for(r=new(void 0===n?Array:n)(m(_-b,0)),l=0;b<_;b++,l++)b in d&&u(r,l,d[b]);return r.length=l,r}})},fc6a:function(t,e,n){var r=n("44ad"),i=n("1d80");t.exports=function(t){return r(i(t))}},fd7e:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration var e=t.defineLocale("x-pseudo",{months:"J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér".split("_"),monthsShort:"J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc".split("_"),monthsParseExact:!0,weekdays:"S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý".split("_"),weekdaysShort:"S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát".split("_"),weekdaysMin:"S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[T~ódá~ý át] LT",nextDay:"[T~ómó~rró~w át] LT",nextWeek:"dddd [át] LT",lastDay:"[Ý~ést~érdá~ý át] LT",lastWeek:"[L~ást] dddd [át] LT",sameElse:"L"},relativeTime:{future:"í~ñ %s",past:"%s á~gó",s:"á ~féw ~sécó~ñds",ss:"%d s~écóñ~ds",m:"á ~míñ~úté",mm:"%d m~íñú~tés",h:"á~ñ hó~úr",hh:"%d h~óúrs",d:"á ~dáý",dd:"%d d~áýs",M:"á ~móñ~th",MM:"%d m~óñt~hs",y:"á ~ýéár",yy:"%d ý~éárs"},dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10,n=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+n},week:{dow:1,doy:4}});return e}))},fdbc:function(t,e){t.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},fdbf:function(t,e,n){var r=n("4930");t.exports=r&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},fea9:function(t,e,n){var r=n("da84");t.exports=r.Promise},ffff:function(t,e,n){(function(t,e){e(n("c1df"))})(0,(function(t){"use strict"; //! moment.js locale configuration diff --git a/cookbook/static/vue/js/offline_view.js b/cookbook/static/vue/js/offline_view.js index 08531bef..c6371065 100644 --- a/cookbook/static/vue/js/offline_view.js +++ b/cookbook/static/vue/js/offline_view.js @@ -1 +1 @@ -(function(e){function t(t){for(var s,c,f=t[0],o=t[1],i=t[2],u=0,j=[];ut[n.id].updated_at&&(t[n.id]=n):t[n.id]=n)})),t}},data:function(){return{recipes:[],filter:""}},mounted:function(){this.loadRecipe()},methods:{formatDateTime:function(e){return i.a.locale(window.navigator.language),i()(e).format("LLL")},loadRecipe:function(){var e=this;caches.open("api-recipe").then((function(t){t.keys().then((function(t){t.forEach((function(t){caches.match(t).then((function(t){t.json().then((function(t){e.recipes.push(t)}))}))}))}))}))}}},u=d,j=n("2877"),l=Object(j["a"])(u,a,r,!1,null,null,null),b=l.exports;s["default"].config.productionTip=!1,new s["default"]({render:function(e){return e(b)}}).$mount("#app")},fa7d:function(e,t,n){"use strict";n.d(t,"c",(function(){return r})),n.d(t,"f",(function(){return c})),n.d(t,"a",(function(){return f})),n.d(t,"e",(function(){return o})),n.d(t,"b",(function(){return i})),n.d(t,"g",(function(){return d})),n.d(t,"d",(function(){return j}));n("99af");var s=n("59e4");function a(e,t,n){var s=Math.floor(e),a=1,r=s+1,c=1;if(e!==s)while(a<=t&&c<=t){var f=(s+r)/(a+c);if(e===f){a+c<=t?(a+=c,s+=r,c=t+1):a>c?c=t+1:a=t+1;break}et&&(a=c,s=r),!n)return[0,s,a];var o=Math.floor(s/a);return[o,s-o*a,a]}var r={methods:{makeToast:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return c(e,t,n)}}};function c(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new s["a"];a.$bvToast.toast(t,{title:e,variant:n,toaster:"b-toaster-top-center",solid:!0})}var f={methods:{_:function(e){return o(e)}}};function o(e){return window.gettext(e)}var i={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function u(e){return window.USER_PREF[e]}function j(e,t){if(u("use_fractions")){var n="",s=a(e*t,9,!0);return s[0]>0&&(n+=s[0]),s[1]>0&&(n+=" ".concat(s[1],"").concat(s[2],"")),n}return l(e*t)}function l(e){var t=u("user_fractions")?u("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file +(function(e){function t(t){for(var s,c,f=t[0],o=t[1],i=t[2],u=0,j=[];ut[n.id].updated_at&&(t[n.id]=n):t[n.id]=n)})),t}},data:function(){return{recipes:[],filter:""}},mounted:function(){this.loadRecipe()},methods:{formatDateTime:function(e){return i.a.locale(window.navigator.language),i()(e).format("LLL")},loadRecipe:function(){var e=this;caches.open("api-recipe").then((function(t){t.keys().then((function(t){t.forEach((function(t){caches.match(t).then((function(t){t.json().then((function(t){e.recipes.push(t)}))}))}))}))}))}}},u=d,j=n("2877"),l=Object(j["a"])(u,a,r,!1,null,null,null),b=l.exports;s["default"].config.productionTip=!1,new s["default"]({render:function(e){return e(b)}}).$mount("#app")},fa7d:function(e,t,n){"use strict";n.d(t,"c",(function(){return r})),n.d(t,"f",(function(){return c})),n.d(t,"a",(function(){return f})),n.d(t,"e",(function(){return o})),n.d(t,"b",(function(){return i})),n.d(t,"g",(function(){return d})),n.d(t,"d",(function(){return j}));n("99af");var s=n("59e4");function a(e,t,n){var s=Math.floor(e),a=1,r=s+1,c=1;if(e!==s)while(a<=t&&c<=t){var f=(s+r)/(a+c);if(e===f){a+c<=t?(a+=c,s+=r,c=t+1):a>c?c=t+1:a=t+1;break}et&&(a=c,s=r),!n)return[0,s,a];var o=Math.floor(s/a);return[o,s-o*a,a]}var r={methods:{makeToast:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return c(e,t,n)}}};function c(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new s["a"];a.$bvToast.toast(t,{title:e,variant:n,toaster:"b-toaster-top-center",solid:!0})}var f={methods:{_:function(e){return o(e)}}};function o(e){return window.gettext(e)}var i={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function u(e){return window.USER_PREF[e]}function j(e,t){if(u("use_fractions")){var n="",s=a(e*t,9,!0);return s[0]>0&&(n+=s[0]),s[1]>0&&(n+=" ".concat(s[1],"").concat(s[2],"")),n}return l(e*t)}function l(e){var t=u("user_fractions")?u("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file diff --git a/cookbook/templates/sw.js b/cookbook/templates/sw.js index e9eb4e3c..5924313c 100644 --- a/cookbook/templates/sw.js +++ b/cookbook/templates/sw.js @@ -1 +1 @@ -(function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"===typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(r,o,function(e){return t[e]}.bind(null,o));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t["default"]}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s="249e")})({"00ee":function(t,e,n){var r=n("b622"),o=r("toStringTag"),i={};i[o]="z",t.exports="[object z]"===String(i)},"06cf":function(t,e,n){var r=n("83ab"),o=n("d1e7"),i=n("5c6c"),a=n("fc6a"),c=n("c04e"),s=n("5135"),u=n("0cfb"),l=Object.getOwnPropertyDescriptor;e.f=r?l:function(t,e){if(t=a(t),e=c(e,!0),u)try{return l(t,e)}catch(n){}if(s(t,e))return i(!o.f.call(t,e),t[e])}},"0cfb":function(t,e,n){var r=n("83ab"),o=n("d039"),i=n("cc12");t.exports=!r&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},"14c3":function(t,e,n){var r=n("c6b6"),o=n("9263");t.exports=function(t,e){var n=t.exec;if("function"===typeof n){var i=n.call(t,e);if("object"!==typeof i)throw TypeError("RegExp exec method returned something other than an Object or null");return i}if("RegExp"!==r(t))throw TypeError("RegExp#exec called on incompatible receiver");return o.call(t,e)}},"1d80":function(t,e){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},"23cb":function(t,e,n){var r=n("a691"),o=Math.max,i=Math.min;t.exports=function(t,e){var n=r(t);return n<0?o(n+e,0):i(n,e)}},"23e7":function(t,e,n){var r=n("da84"),o=n("06cf").f,i=n("9112"),a=n("6eeb"),c=n("ce4e"),s=n("e893"),u=n("94ca");t.exports=function(t,e){var n,l,f,h,p,d,g=t.target,y=t.global,m=t.stat;if(l=y?r:m?r[g]||c(g,{}):(r[g]||{}).prototype,l)for(f in e){if(p=e[f],t.noTargetGet?(d=o(l,f),h=d&&d.value):h=l[f],n=u(y?f:g+(m?".":"#")+f,t.forced),!n&&void 0!==h){if(typeof p===typeof h)continue;s(p,h)}(t.sham||h&&h.sham)&&i(p,"sham",!0),a(l,f,p,t)}}},"241c":function(t,e,n){var r=n("ca84"),o=n("7839"),i=o.concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return r(t,i)}},"249e":function(t,e,n){"use strict";n.r(e);n("4d63"),n("ac1f"),n("25f0"),n("466d"),n("96cf"),n("d3b7");function r(t,e,n,r,o,i,a){try{var c=t[i](a),s=c.value}catch(u){return void n(u)}c.done?e(s):Promise.resolve(s).then(r,o)}function o(t){return function(){var e=this,n=arguments;return new Promise((function(o,i){var a=t.apply(e,n);function c(t){r(a,o,i,c,s,"next",t)}function s(t){r(a,o,i,c,s,"throw",t)}c(void 0)}))}}n("40b9");Error;"undefined"!==typeof registration&®istration.scope;n("c700");n("741b");const i={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!==typeof registration?registration.scope:""},a=t=>[i.prefix,t,i.suffix].filter(t=>t&&t.length>0).join("-"),c=t=>{for(const e of Object.keys(i))t(e)},s={updateDetails:t=>{c(e=>{"string"===typeof t[e]&&(i[e]=t[e])})},getGoogleAnalyticsName:t=>t||a(i.googleAnalytics),getPrecacheName:t=>t||a(i.precache),getPrefix:()=>i.prefix,getRuntimeName:t=>t||a(i.runtime),getSuffix:()=>i.suffix},u=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},l=u;class f extends Error{constructor(t,e){const n=l(t,e);super(n),this.name=t,this.details=e}}const h=t=>{const e=new URL(String(t),location.href);return e.href.replace(new RegExp("^"+location.origin),"")};function p(t,e){const n=new URL(t);for(const r of e)n.searchParams.delete(r);return n.href}async function d(t,e,n,r){const o=p(e.url,n);if(e.url===o)return t.match(e,r);const i={...r,ignoreSearch:!0},a=await t.keys(e,i);for(const c of a){const e=p(c.url,n);if(o===e)return t.match(c,r)}}class g{constructor(){this.promise=new Promise((t,e)=>{this.resolve=t,this.reject=e})}}const y=new Set;async function m(){for(const t of y)await t()}function v(t){return new Promise(e=>setTimeout(e,t))}n("6aa8");function w(t){return"string"===typeof t?new Request(t):t}class x{constructor(t,e){this._cacheKeys={},Object.assign(this,e),this.event=e.event,this._strategy=t,this._handlerDeferred=new g,this._extendLifetimePromises=[],this._plugins=[...t.plugins],this._pluginStateMap=new Map;for(const n of this._plugins)this._pluginStateMap.set(n,{});this.event.waitUntil(this._handlerDeferred.promise)}fetch(t){return this.waitUntil((async()=>{const{event:e}=this;let n=w(t);if("navigate"===n.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const r=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))n=await t({request:n.clone(),event:e})}catch(i){throw new f("plugin-error-request-will-fetch",{thrownError:i})}const o=n.clone();try{let t;t=await fetch(n,"navigate"===n.mode?void 0:this._strategy.fetchOptions);for(const n of this.iterateCallbacks("fetchDidSucceed"))t=await n({event:e,request:o,response:t});return t}catch(a){throw r&&await this.runCallbacks("fetchDidFail",{error:a,event:e,originalRequest:r.clone(),request:o.clone()}),a}})())}async fetchAndCachePut(t){const e=await this.fetch(t),n=e.clone();return this.waitUntil(this.cachePut(t,n)),e}cacheMatch(t){return this.waitUntil((async()=>{const e=w(t);let n;const{cacheName:r,matchOptions:o}=this._strategy,i=await this.getCacheKey(e,"read"),a={...o,cacheName:r};n=await caches.match(i,a);for(const t of this.iterateCallbacks("cachedResponseWillBeUsed"))n=await t({cacheName:r,matchOptions:o,cachedResponse:n,request:i,event:this.event})||void 0;return n})())}async cachePut(t,e){const n=w(t);await v(0);const r=await this.getCacheKey(n,"write");if(!e)throw new f("cache-put-with-no-response",{url:h(r.url)});const o=await this._ensureResponseSafeToCache(e);if(!o)return void 0;const{cacheName:i,matchOptions:a}=this._strategy,c=await self.caches.open(i),s=this.hasCallback("cacheDidUpdate"),u=s?await d(c,r.clone(),["__WB_REVISION__"],a):null;try{await c.put(r,s?o.clone():o)}catch(l){throw"QuotaExceededError"===l.name&&await m(),l}for(const f of this.iterateCallbacks("cacheDidUpdate"))await f({cacheName:i,oldResponse:u,newResponse:o.clone(),request:r,event:this.event})}async getCacheKey(t,e){if(!this._cacheKeys[e]){let n=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))n=w(await t({mode:e,request:n,event:this.event,params:this.params}));this._cacheKeys[e]=n}return this._cacheKeys[e]}hasCallback(t){for(const e of this._strategy.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const n of this.iterateCallbacks(t))await n(e)}*iterateCallbacks(t){for(const e of this._strategy.plugins)if("function"===typeof e[t]){const n=this._pluginStateMap.get(e),r=r=>{const o={...r,state:n};return e[t](o)};yield r}}waitUntil(t){return this._extendLifetimePromises.push(t),t}async doneWaiting(){let t;while(t=this._extendLifetimePromises.shift())await t}destroy(){this._handlerDeferred.resolve()}async _ensureResponseSafeToCache(t){let e=t,n=!1;for(const r of this.iterateCallbacks("cacheWillUpdate"))if(e=await r({request:this.request,response:e,event:this.event})||void 0,n=!0,!e)break;return n||e&&200!==e.status&&(e=void 0),e}}class b{constructor(t={}){this.cacheName=s.getRuntimeName(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,n="string"===typeof t.request?new Request(t.request):t.request,r="params"in t?t.params:void 0,o=new x(this,{event:e,request:n,params:r}),i=this._getResponse(o,n,e),a=this._awaitComplete(i,o,n,e);return[i,a]}async _getResponse(t,e,n){await t.runCallbacks("handlerWillStart",{event:n,request:e});let r=void 0;try{if(r=await this._handle(e,t),!r||"error"===r.type)throw new f("no-response",{url:e.url})}catch(o){for(const i of t.iterateCallbacks("handlerDidError"))if(r=await i({error:o,event:n,request:e}),r)break;if(!r)throw o}for(const i of t.iterateCallbacks("handlerWillRespond"))r=await i({event:n,request:e,response:r});return r}async _awaitComplete(t,e,n,r){let o,i;try{o=await t}catch(i){}try{await e.runCallbacks("handlerDidRespond",{event:r,request:n,response:o}),await e.doneWaiting()}catch(a){i=a}if(await e.runCallbacks("handlerDidComplete",{event:r,request:n,response:o,error:i}),e.destroy(),i)throw i}}n("95a8");const _=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},E=_;class S extends Error{constructor(t,e){const n=E(t,e);super(n),this.name=t,this.details=e}}n("e6d2");const R="GET",O=t=>t&&"object"===typeof t?t:{handle:t};class P{constructor(t,e,n=R){this.handler=O(e),this.match=t,this.method=n}}class N extends P{constructor(t,e,n){const r=({url:e})=>{const n=t.exec(e.href);if(n&&(e.origin===location.origin||0===n.index))return n.slice(1)};super(r,e,n)}}class j{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener("fetch",t=>{const{request:e}=t,n=this.handleRequest({request:e,event:t});n&&t.respondWith(n)})}addCacheListener(){self.addEventListener("message",t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data;0;const n=Promise.all(e.urlsToCache.map(e=>{"string"===typeof e&&(e=[e]);const n=new Request(...e);return this.handleRequest({request:n,event:t})}));t.waitUntil(n),t.ports&&t.ports[0]&&n.then(()=>t.ports[0].postMessage(!0))}})}handleRequest({request:t,event:e}){const n=new URL(t.url,location.href);if(!n.protocol.startsWith("http"))return void 0;const r=n.origin===location.origin,{params:o,route:i}=this.findMatchingRoute({event:e,request:t,sameOrigin:r,url:n});let a=i&&i.handler;const c=t.method;if(!a&&this._defaultHandlerMap.has(c)&&(a=this._defaultHandlerMap.get(c)),!a)return void 0;let s;try{s=a.handle({url:n,request:t,event:e,params:o})}catch(u){s=Promise.reject(u)}return s instanceof Promise&&this._catchHandler&&(s=s.catch(r=>this._catchHandler.handle({url:n,request:t,event:e}))),s}findMatchingRoute({url:t,sameOrigin:e,request:n,event:r}){const o=this._routes.get(n.method)||[];for(const i of o){let o;const a=i.match({url:t,sameOrigin:e,request:n,event:r});if(a)return o=a,(Array.isArray(a)&&0===a.length||a.constructor===Object&&0===Object.keys(a).length||"boolean"===typeof a)&&(o=void 0),{route:i,params:o}}return{}}setDefaultHandler(t,e=R){this._defaultHandlerMap.set(e,O(t))}setCatchHandler(t){this._catchHandler=O(t)}registerRoute(t){this._routes.has(t.method)||this._routes.set(t.method,[]),this._routes.get(t.method).push(t)}unregisterRoute(t){if(!this._routes.has(t.method))throw new S("unregister-route-but-not-found-with-method",{method:t.method});const e=this._routes.get(t.method).indexOf(t);if(!(e>-1))throw new S("unregister-route-route-not-registered");this._routes.get(t.method).splice(e,1)}}let k;const T=()=>(k||(k=new j,k.addFetchListener(),k.addCacheListener()),k);function q(t,e,n){let r;if("string"===typeof t){const o=new URL(t,location.href);0;const i=({url:t})=>t.href===o.href;r=new P(i,e,n)}else if(t instanceof RegExp)r=new N(t,e,n);else if("function"===typeof t)r=new P(t,e,n);else{if(!(t instanceof P))throw new S("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});r=t}const o=T();return o.registerRoute(r),r}function A(t){const e=T();e.setCatchHandler(t)}class C extends b{async _handle(t,e){let n,r=await e.cacheMatch(t);if(r)0;else{0;try{r=await e.fetchAndCachePut(t)}catch(o){n=o}0}if(!r)throw new f("no-response",{url:t.url,error:n});return r}}const L={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null};class M extends b{constructor(t={}){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(L),this._networkTimeoutSeconds=t.networkTimeoutSeconds||0}async _handle(t,e){const n=[];const r=[];let o;if(this._networkTimeoutSeconds){const{id:i,promise:a}=this._getTimeoutPromise({request:t,logs:n,handler:e});o=i,r.push(a)}const i=this._getNetworkPromise({timeoutId:o,request:t,logs:n,handler:e});r.push(i);for(const c of r)e.waitUntil(c);let a=await Promise.race(r);if(a||(a=await i),!a)throw new f("no-response",{url:t.url});return a}_getTimeoutPromise({request:t,logs:e,handler:n}){let r;const o=new Promise(e=>{const o=async()=>{e(await n.cacheMatch(t))};r=setTimeout(o,1e3*this._networkTimeoutSeconds)});return{promise:o,id:r}}async _getNetworkPromise({timeoutId:t,request:e,logs:n,handler:r}){let o,i;try{i=await r.fetchAndCachePut(e)}catch(a){o=a}return t&&clearTimeout(t),!o&&i||(i=await r.cacheMatch(e)),i}}class U extends b{constructor(t){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(L)}async _handle(t,e){const n=e.fetchAndCachePut(t).catch(()=>{});let r,o=await e.cacheMatch(t);if(o)0;else{0;try{o=await n}catch(i){r=i}}if(!o)throw new f("no-response",{url:t.url,error:r});return o}}n("d2e2");const I=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},D=I;class F extends Error{constructor(t,e){const n=D(t,e);super(n),this.name=t,this.details=e}}function K(t){t.then(()=>{})}class W{constructor(t,e,{onupgradeneeded:n,onversionchange:r}={}){this._db=null,this._name=t,this._version=e,this._onupgradeneeded=n,this._onversionchange=r||(()=>this.close())}get db(){return this._db}async open(){if(!this._db)return this._db=await new Promise((t,e)=>{let n=!1;setTimeout(()=>{n=!0,e(new Error("The open request was blocked and timed out"))},this.OPEN_TIMEOUT);const r=indexedDB.open(this._name,this._version);r.onerror=()=>e(r.error),r.onupgradeneeded=t=>{n?(r.transaction.abort(),r.result.close()):"function"===typeof this._onupgradeneeded&&this._onupgradeneeded(t)},r.onsuccess=()=>{const e=r.result;n?e.close():(e.onversionchange=this._onversionchange.bind(this),t(e))}}),this}async getKey(t,e){return(await this.getAllKeys(t,e,1))[0]}async getAll(t,e,n){return await this.getAllMatching(t,{query:e,count:n})}async getAllKeys(t,e,n){const r=await this.getAllMatching(t,{query:e,count:n,includeKeys:!0});return r.map(t=>t.key)}async getAllMatching(t,{index:e,query:n=null,direction:r="next",count:o,includeKeys:i=!1}={}){return await this.transaction([t],"readonly",(a,c)=>{const s=a.objectStore(t),u=e?s.index(e):s,l=[],f=u.openCursor(n,r);f.onsuccess=()=>{const t=f.result;t?(l.push(i?t:t.value),o&&l.length>=o?c(l):t.continue()):c(l)}})}async transaction(t,e,n){return await this.open(),await new Promise((r,o)=>{const i=this._db.transaction(t,e);i.onabort=()=>o(i.error),i.oncomplete=()=>r(),n(i,t=>r(t))})}async _call(t,e,n,...r){const o=(n,o)=>{const i=n.objectStore(e),a=i[t].apply(i,r);a.onsuccess=()=>o(a.result)};return await this.transaction([e],n,o)}close(){this._db&&(this._db.close(),this._db=null)}}W.prototype.OPEN_TIMEOUT=2e3;const G={readonly:["get","count","getKey","getAll","getAllKeys"],readwrite:["add","put","clear","delete"]};for(const[it,at]of Object.entries(G))for(const t of at)t in IDBObjectStore.prototype&&(W.prototype[t]=async function(e,...n){return await this._call(t,e,it,...n)});const H=async t=>{await new Promise((e,n)=>{const r=indexedDB.deleteDatabase(t);r.onerror=()=>{n(r.error)},r.onblocked=()=>{n(new Error("Delete blocked"))},r.onsuccess=()=>{e()}})};n("d8a5");const B="workbox-expiration",Y="cache-entries",$=t=>{const e=new URL(t,location.href);return e.hash="",e.href};class z{constructor(t){this._cacheName=t,this._db=new W(B,1,{onupgradeneeded:t=>this._handleUpgrade(t)})}_handleUpgrade(t){const e=t.target.result,n=e.createObjectStore(Y,{keyPath:"id"});n.createIndex("cacheName","cacheName",{unique:!1}),n.createIndex("timestamp","timestamp",{unique:!1}),H(this._cacheName)}async setTimestamp(t,e){t=$(t);const n={url:t,timestamp:e,cacheName:this._cacheName,id:this._getId(t)};await this._db.put(Y,n)}async getTimestamp(t){const e=await this._db.get(Y,this._getId(t));return e.timestamp}async expireEntries(t,e){const n=await this._db.transaction(Y,"readwrite",(n,r)=>{const o=n.objectStore(Y),i=o.index("timestamp").openCursor(null,"prev"),a=[];let c=0;i.onsuccess=()=>{const n=i.result;if(n){const r=n.value;r.cacheName===this._cacheName&&(t&&r.timestamp=e?a.push(n.value):c++),n.continue()}else r(a)}}),r=[];for(const o of n)await this._db.delete(Y,o.id),r.push(o.url);return r}_getId(t){return this._cacheName+"|"+$(t)}}class J{constructor(t,e={}){this._isRunning=!1,this._rerunRequested=!1,this._maxEntries=e.maxEntries,this._maxAgeSeconds=e.maxAgeSeconds,this._matchOptions=e.matchOptions,this._cacheName=t,this._timestampModel=new z(t)}async expireEntries(){if(this._isRunning)return void(this._rerunRequested=!0);this._isRunning=!0;const t=this._maxAgeSeconds?Date.now()-1e3*this._maxAgeSeconds:0,e=await this._timestampModel.expireEntries(t,this._maxEntries),n=await self.caches.open(this._cacheName);for(const r of e)await n.delete(r,this._matchOptions);this._isRunning=!1,this._rerunRequested&&(this._rerunRequested=!1,K(this.expireEntries()))}async updateTimestamp(t){await this._timestampModel.setTimestamp(t,Date.now())}async isURLExpired(t){if(this._maxAgeSeconds){const e=await this._timestampModel.getTimestamp(t),n=Date.now()-1e3*this._maxAgeSeconds;return e[Q.prefix,t,Q.suffix].filter(t=>t&&t.length>0).join("-"),X=t=>{for(const e of Object.keys(Q))t(e)},Z={updateDetails:t=>{X(e=>{"string"===typeof t[e]&&(Q[e]=t[e])})},getGoogleAnalyticsName:t=>t||V(Q.googleAnalytics),getPrecacheName:t=>t||V(Q.precache),getPrefix:()=>Q.prefix,getRuntimeName:t=>t||V(Q.runtime),getSuffix:()=>Q.suffix},tt=new Set;function et(t){tt.add(t)}class nt{constructor(t={}){this.cachedResponseWillBeUsed=async({event:t,request:e,cacheName:n,cachedResponse:r})=>{if(!r)return null;const o=this._isResponseDateFresh(r),i=this._getCacheExpiration(n);K(i.expireEntries());const a=i.updateTimestamp(e.url);if(t)try{t.waitUntil(a)}catch(c){0}return o?r:null},this.cacheDidUpdate=async({cacheName:t,request:e})=>{const n=this._getCacheExpiration(t);await n.updateTimestamp(e.url),await n.expireEntries()},this._config=t,this._maxAgeSeconds=t.maxAgeSeconds,this._cacheExpirations=new Map,t.purgeOnQuotaError&&et(()=>this.deleteCacheAndMetadata())}_getCacheExpiration(t){if(t===Z.getRuntimeName())throw new F("expire-custom-caches-only");let e=this._cacheExpirations.get(t);return e||(e=new J(t,this._config),this._cacheExpirations.set(t,e)),e}_isResponseDateFresh(t){if(!this._maxAgeSeconds)return!0;const e=this._getDateHeaderTimestamp(t);if(null===e)return!0;const n=Date.now();return e>=n-1e3*this._maxAgeSeconds}_getDateHeaderTimestamp(t){if(!t.headers.has("date"))return null;const e=t.headers.get("date"),n=new Date(e),r=n.getTime();return isNaN(r)?null:r}async deleteCacheAndMetadata(){for(const[t,e]of this._cacheExpirations)await self.caches.delete(t),await e.delete();this._cacheExpirations=new Map}}var rt="offline-html",ot="/offline/";self.addEventListener("install",function(){var t=o(regeneratorRuntime.mark((function t(e){return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:e.waitUntil(caches.open(rt).then((function(t){return t.add(new Request(ot,{cache:"reload"}))})));case 1:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}()),[{'url':'static/vue/css/chunk-vendors.css'},{'url':'static/vue/js/chunk-vendors.js'},{'url':'static/vue/js/offline_view.js'},{'url':'static/vue/js/recipe_view.js'},{'url':'static/vue/manifest.json'},{'url':'static/vue/offline_view.html'},{'url':'static/vue/recipe_view.html'}],A((function(t){var e=t.event;switch(e.request.destination){case"document":return console.log("Triggered fallback HTML"),caches.open(rt).then((function(t){return t.match(ot)}));default:return console.log("Triggered response ERROR"),Response.error()}})),q((function(t){var e=t.request;return"image"===e.destination}),new C({cacheName:"images",plugins:[new nt({maxEntries:20})]})),q((function(t){var e=t.request;return"script"===e.destination||"style"===e.destination}),new U({cacheName:"assets"})),q(new RegExp("jsreverse"),new U({cacheName:"assets"})),q(new RegExp("jsi18n"),new U({cacheName:"assets"})),q(new RegExp("api/recipe/([0-9]+)"),new M({cacheName:"api-recipe",plugins:[new nt({maxEntries:50})]})),q(new RegExp("api/*"),new M({cacheName:"api",plugins:[new nt({maxEntries:50})]})),q((function(t){var e=t.request;return"document"===e.destination}),new M({cacheName:"html",plugins:[new nt({maxAgeSeconds:2592e3,maxEntries:50})]}))},"25f0":function(t,e,n){"use strict";var r=n("6eeb"),o=n("825a"),i=n("d039"),a=n("ad6d"),c="toString",s=RegExp.prototype,u=s[c],l=i((function(){return"/a/b"!=u.call({source:"a",flags:"b"})})),f=u.name!=c;(l||f)&&r(RegExp.prototype,c,(function(){var t=o(this),e=String(t.source),n=t.flags,r=String(void 0===n&&t instanceof RegExp&&!("flags"in s)?a.call(t):n);return"/"+e+"/"+r}),{unsafe:!0})},2626:function(t,e,n){"use strict";var r=n("d066"),o=n("9bf2"),i=n("b622"),a=n("83ab"),c=i("species");t.exports=function(t){var e=r(t),n=o.f;a&&e&&!e[c]&&n(e,c,{configurable:!0,get:function(){return this}})}},"3bbe":function(t,e,n){var r=n("861d");t.exports=function(t){if(!r(t)&&null!==t)throw TypeError("Can't set "+String(t)+" as a prototype");return t}},"40b9":function(t,e,n){"use strict";try{self["workbox:core:6.0.2"]&&_()}catch(r){}},"428f":function(t,e,n){var r=n("da84");t.exports=r},"44ad":function(t,e,n){var r=n("d039"),o=n("c6b6"),i="".split;t.exports=r((function(){return!Object("z").propertyIsEnumerable(0)}))?function(t){return"String"==o(t)?i.call(t,""):Object(t)}:Object},"44e7":function(t,e,n){var r=n("861d"),o=n("c6b6"),i=n("b622"),a=i("match");t.exports=function(t){var e;return r(t)&&(void 0!==(e=t[a])?!!e:"RegExp"==o(t))}},"466d":function(t,e,n){"use strict";var r=n("d784"),o=n("825a"),i=n("50c4"),a=n("1d80"),c=n("8aa5"),s=n("14c3");r("match",1,(function(t,e,n){return[function(e){var n=a(this),r=void 0==e?void 0:e[t];return void 0!==r?r.call(e,n):new RegExp(e)[t](String(n))},function(t){var r=n(e,t,this);if(r.done)return r.value;var a=o(t),u=String(this);if(!a.global)return s(a,u);var l=a.unicode;a.lastIndex=0;var f,h=[],p=0;while(null!==(f=s(a,u))){var d=String(f[0]);h[p]=d,""===d&&(a.lastIndex=c(u,i(a.lastIndex),l)),p++}return 0===p?null:h}]}))},4930:function(t,e,n){var r=n("d039");t.exports=!!Object.getOwnPropertySymbols&&!r((function(){return!String(Symbol())}))},"4d63":function(t,e,n){var r=n("83ab"),o=n("da84"),i=n("94ca"),a=n("7156"),c=n("9bf2").f,s=n("241c").f,u=n("44e7"),l=n("ad6d"),f=n("9f7f"),h=n("6eeb"),p=n("d039"),d=n("69f3").set,g=n("2626"),y=n("b622"),m=y("match"),v=o.RegExp,w=v.prototype,x=/a/g,b=/a/g,_=new v(x)!==x,E=f.UNSUPPORTED_Y,S=r&&i("RegExp",!_||E||p((function(){return b[m]=!1,v(x)!=x||v(b)==b||"/a/i"!=v(x,"i")})));if(S){var R=function(t,e){var n,r=this instanceof R,o=u(t),i=void 0===e;if(!r&&o&&t.constructor===R&&i)return t;_?o&&!i&&(t=t.source):t instanceof R&&(i&&(e=l.call(t)),t=t.source),E&&(n=!!e&&e.indexOf("y")>-1,n&&(e=e.replace(/y/g,"")));var c=a(_?new v(t,e):v(t,e),r?this:w,R);return E&&n&&d(c,{sticky:n}),c},O=function(t){t in R||c(R,t,{configurable:!0,get:function(){return v[t]},set:function(e){v[t]=e}})},P=s(v),N=0;while(P.length>N)O(P[N++]);w.constructor=R,R.prototype=w,h(o,"RegExp",R)}g("RegExp")},"4d64":function(t,e,n){var r=n("fc6a"),o=n("50c4"),i=n("23cb"),a=function(t){return function(e,n,a){var c,s=r(e),u=o(s.length),l=i(a,u);if(t&&n!=n){while(u>l)if(c=s[l++],c!=c)return!0}else for(;u>l;l++)if((t||l in s)&&s[l]===n)return t||l||0;return!t&&-1}};t.exports={includes:a(!0),indexOf:a(!1)}},"50c4":function(t,e,n){var r=n("a691"),o=Math.min;t.exports=function(t){return t>0?o(r(t),9007199254740991):0}},5135:function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},5692:function(t,e,n){var r=n("c430"),o=n("c6cd");(t.exports=function(t,e){return o[t]||(o[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.8.2",mode:r?"pure":"global",copyright:"© 2021 Denis Pushkarev (zloirock.ru)"})},"56ef":function(t,e,n){var r=n("d066"),o=n("241c"),i=n("7418"),a=n("825a");t.exports=r("Reflect","ownKeys")||function(t){var e=o.f(a(t)),n=i.f;return n?e.concat(n(t)):e}},"5c6c":function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},6547:function(t,e,n){var r=n("a691"),o=n("1d80"),i=function(t){return function(e,n){var i,a,c=String(o(e)),s=r(n),u=c.length;return s<0||s>=u?t?"":void 0:(i=c.charCodeAt(s),i<55296||i>56319||s+1===u||(a=c.charCodeAt(s+1))<56320||a>57343?t?c.charAt(s):i:t?c.slice(s,s+2):a-56320+(i-55296<<10)+65536)}};t.exports={codeAt:i(!1),charAt:i(!0)}},"69f3":function(t,e,n){var r,o,i,a=n("7f9a"),c=n("da84"),s=n("861d"),u=n("9112"),l=n("5135"),f=n("c6cd"),h=n("f772"),p=n("d012"),d=c.WeakMap,g=function(t){return i(t)?o(t):r(t,{})},y=function(t){return function(e){var n;if(!s(e)||(n=o(e)).type!==t)throw TypeError("Incompatible receiver, "+t+" required");return n}};if(a){var m=f.state||(f.state=new d),v=m.get,w=m.has,x=m.set;r=function(t,e){return e.facade=t,x.call(m,t,e),e},o=function(t){return v.call(m,t)||{}},i=function(t){return w.call(m,t)}}else{var b=h("state");p[b]=!0,r=function(t,e){return e.facade=t,u(t,b,e),e},o=function(t){return l(t,b)?t[b]:{}},i=function(t){return l(t,b)}}t.exports={set:r,get:o,has:i,enforce:g,getterFor:y}},"6aa8":function(t,e,n){"use strict";try{self["workbox:strategies:6.0.2"]&&_()}catch(r){}},"6eeb":function(t,e,n){var r=n("da84"),o=n("9112"),i=n("5135"),a=n("ce4e"),c=n("8925"),s=n("69f3"),u=s.get,l=s.enforce,f=String(String).split("String");(t.exports=function(t,e,n,c){var s,u=!!c&&!!c.unsafe,h=!!c&&!!c.enumerable,p=!!c&&!!c.noTargetGet;"function"==typeof n&&("string"!=typeof e||i(n,"name")||o(n,"name",e),s=l(n),s.source||(s.source=f.join("string"==typeof e?e:""))),t!==r?(u?!p&&t[e]&&(h=!0):delete t[e],h?t[e]=n:o(t,e,n)):h?t[e]=n:a(e,n)})(Function.prototype,"toString",(function(){return"function"==typeof this&&u(this).source||c(this)}))},7156:function(t,e,n){var r=n("861d"),o=n("d2bb");t.exports=function(t,e,n){var i,a;return o&&"function"==typeof(i=e.constructor)&&i!==n&&r(a=i.prototype)&&a!==n.prototype&&o(t,a),t}},7418:function(t,e){e.f=Object.getOwnPropertySymbols},"741b":function(t,e,n){"use strict";try{self["workbox:core:6.0.2"]&&_()}catch(r){}},7839:function(t,e){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},"7f9a":function(t,e,n){var r=n("da84"),o=n("8925"),i=r.WeakMap;t.exports="function"===typeof i&&/native code/.test(o(i))},"825a":function(t,e,n){var r=n("861d");t.exports=function(t){if(!r(t))throw TypeError(String(t)+" is not an object");return t}},"83ab":function(t,e,n){var r=n("d039");t.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},"861d":function(t,e){t.exports=function(t){return"object"===typeof t?null!==t:"function"===typeof t}},8925:function(t,e,n){var r=n("c6cd"),o=Function.toString;"function"!=typeof r.inspectSource&&(r.inspectSource=function(t){return o.call(t)}),t.exports=r.inspectSource},"8aa5":function(t,e,n){"use strict";var r=n("6547").charAt;t.exports=function(t,e,n){return e+(n?r(t,e).length:1)}},"90e3":function(t,e){var n=0,r=Math.random();t.exports=function(t){return"Symbol("+String(void 0===t?"":t)+")_"+(++n+r).toString(36)}},9112:function(t,e,n){var r=n("83ab"),o=n("9bf2"),i=n("5c6c");t.exports=r?function(t,e,n){return o.f(t,e,i(1,n))}:function(t,e,n){return t[e]=n,t}},9263:function(t,e,n){"use strict";var r=n("ad6d"),o=n("9f7f"),i=RegExp.prototype.exec,a=String.prototype.replace,c=i,s=function(){var t=/a/,e=/b*/g;return i.call(t,"a"),i.call(e,"a"),0!==t.lastIndex||0!==e.lastIndex}(),u=o.UNSUPPORTED_Y||o.BROKEN_CARET,l=void 0!==/()??/.exec("")[1],f=s||l||u;f&&(c=function(t){var e,n,o,c,f=this,h=u&&f.sticky,p=r.call(f),d=f.source,g=0,y=t;return h&&(p=p.replace("y",""),-1===p.indexOf("g")&&(p+="g"),y=String(t).slice(f.lastIndex),f.lastIndex>0&&(!f.multiline||f.multiline&&"\n"!==t[f.lastIndex-1])&&(d="(?: "+d+")",y=" "+y,g++),n=new RegExp("^(?:"+d+")",p)),l&&(n=new RegExp("^"+d+"$(?!\\s)",p)),s&&(e=f.lastIndex),o=i.call(h?n:f,y),h?o?(o.input=o.input.slice(g),o[0]=o[0].slice(g),o.index=f.lastIndex,f.lastIndex+=o[0].length):f.lastIndex=0:s&&o&&(f.lastIndex=f.global?o.index+o[0].length:e),l&&o&&o.length>1&&a.call(o[0],n,(function(){for(c=1;c=0;--i){var a=this.tryEntries[i],c=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var s=r.call(a,"catchLoc"),u=r.call(a,"finallyLoc");if(s&&u){if(this.prev=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&r.call(o,"finallyLoc")&&this.prev=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),N(n),g}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var r=n.completion;if("throw"===r.type){var o=r.arg;N(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,n,r){return this.delegate={iterator:k(t),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=e),g}},t}(t.exports);try{regeneratorRuntime=r}catch(o){Function("r","regeneratorRuntime = r")(r)}},"9bf2":function(t,e,n){var r=n("83ab"),o=n("0cfb"),i=n("825a"),a=n("c04e"),c=Object.defineProperty;e.f=r?c:function(t,e,n){if(i(t),e=a(e,!0),i(n),o)try{return c(t,e,n)}catch(r){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(t[e]=n.value),t}},"9f7f":function(t,e,n){"use strict";var r=n("d039");function o(t,e){return RegExp(t,e)}e.UNSUPPORTED_Y=r((function(){var t=o("a","y");return t.lastIndex=2,null!=t.exec("abcd")})),e.BROKEN_CARET=r((function(){var t=o("^r","gy");return t.lastIndex=2,null!=t.exec("str")}))},a691:function(t,e){var n=Math.ceil,r=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?r:n)(t)}},ac1f:function(t,e,n){"use strict";var r=n("23e7"),o=n("9263");r({target:"RegExp",proto:!0,forced:/./.exec!==o},{exec:o})},ad6d:function(t,e,n){"use strict";var r=n("825a");t.exports=function(){var t=r(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.dotAll&&(e+="s"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},b041:function(t,e,n){"use strict";var r=n("00ee"),o=n("f5df");t.exports=r?{}.toString:function(){return"[object "+o(this)+"]"}},b622:function(t,e,n){var r=n("da84"),o=n("5692"),i=n("5135"),a=n("90e3"),c=n("4930"),s=n("fdbf"),u=o("wks"),l=r.Symbol,f=s?l:l&&l.withoutSetter||a;t.exports=function(t){return i(u,t)||(c&&i(l,t)?u[t]=l[t]:u[t]=f("Symbol."+t)),u[t]}},c04e:function(t,e,n){var r=n("861d");t.exports=function(t,e){if(!r(t))return t;var n,o;if(e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;if("function"==typeof(n=t.valueOf)&&!r(o=n.call(t)))return o;if(!e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;throw TypeError("Can't convert object to primitive value")}},c430:function(t,e){t.exports=!1},c6b6:function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},c6cd:function(t,e,n){var r=n("da84"),o=n("ce4e"),i="__core-js_shared__",a=r[i]||o(i,{});t.exports=a},c700:function(t,e,n){"use strict";try{self["workbox:precaching:6.0.2"]&&_()}catch(r){}},c8ba:function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(r){"object"===typeof window&&(n=window)}t.exports=n},ca84:function(t,e,n){var r=n("5135"),o=n("fc6a"),i=n("4d64").indexOf,a=n("d012");t.exports=function(t,e){var n,c=o(t),s=0,u=[];for(n in c)!r(a,n)&&r(c,n)&&u.push(n);while(e.length>s)r(c,n=e[s++])&&(~i(u,n)||u.push(n));return u}},cc12:function(t,e,n){var r=n("da84"),o=n("861d"),i=r.document,a=o(i)&&o(i.createElement);t.exports=function(t){return a?i.createElement(t):{}}},ce4e:function(t,e,n){var r=n("da84"),o=n("9112");t.exports=function(t,e){try{o(r,t,e)}catch(n){r[t]=e}return e}},d012:function(t,e){t.exports={}},d039:function(t,e){t.exports=function(t){try{return!!t()}catch(e){return!0}}},d066:function(t,e,n){var r=n("428f"),o=n("da84"),i=function(t){return"function"==typeof t?t:void 0};t.exports=function(t,e){return arguments.length<2?i(r[t])||i(o[t]):r[t]&&r[t][e]||o[t]&&o[t][e]}},d1e7:function(t,e,n){"use strict";var r={}.propertyIsEnumerable,o=Object.getOwnPropertyDescriptor,i=o&&!r.call({1:2},1);e.f=i?function(t){var e=o(this,t);return!!e&&e.enumerable}:r},d2bb:function(t,e,n){var r=n("825a"),o=n("3bbe");t.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,n={};try{t=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set,t.call(n,[]),e=n instanceof Array}catch(i){}return function(n,i){return r(n),o(i),e?t.call(n,i):n.__proto__=i,n}}():void 0)},d2e2:function(t,e,n){"use strict";try{self["workbox:core:6.0.2"]&&_()}catch(r){}},d3b7:function(t,e,n){var r=n("00ee"),o=n("6eeb"),i=n("b041");r||o(Object.prototype,"toString",i,{unsafe:!0})},d784:function(t,e,n){"use strict";n("ac1f");var r=n("6eeb"),o=n("d039"),i=n("b622"),a=n("9263"),c=n("9112"),s=i("species"),u=!o((function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")})),l=function(){return"$0"==="a".replace(/./,"$0")}(),f=i("replace"),h=function(){return!!/./[f]&&""===/./[f]("a","$0")}(),p=!o((function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var n="ab".split(t);return 2!==n.length||"a"!==n[0]||"b"!==n[1]}));t.exports=function(t,e,n,f){var d=i(t),g=!o((function(){var e={};return e[d]=function(){return 7},7!=""[t](e)})),y=g&&!o((function(){var e=!1,n=/a/;return"split"===t&&(n={},n.constructor={},n.constructor[s]=function(){return n},n.flags="",n[d]=/./[d]),n.exec=function(){return e=!0,null},n[d](""),!e}));if(!g||!y||"replace"===t&&(!u||!l||h)||"split"===t&&!p){var m=/./[d],v=n(d,""[t],(function(t,e,n,r,o){return e.exec===a?g&&!o?{done:!0,value:m.call(e,n,r)}:{done:!0,value:t.call(n,e,r)}:{done:!1}}),{REPLACE_KEEPS_$0:l,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:h}),w=v[0],x=v[1];r(String.prototype,t,w),r(RegExp.prototype,d,2==e?function(t,e){return x.call(t,this,e)}:function(t){return x.call(t,this)})}f&&c(RegExp.prototype[d],"sham",!0)}},d8a5:function(t,e,n){"use strict";try{self["workbox:expiration:6.0.2"]&&_()}catch(r){}},da84:function(t,e,n){(function(e){var n=function(t){return t&&t.Math==Math&&t};t.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof e&&e)||function(){return this}()||Function("return this")()}).call(this,n("c8ba"))},e6d2:function(t,e,n){"use strict";try{self["workbox:routing:6.0.2"]&&_()}catch(r){}},e893:function(t,e,n){var r=n("5135"),o=n("56ef"),i=n("06cf"),a=n("9bf2");t.exports=function(t,e){for(var n=o(e),c=a.f,s=i.f,u=0;u{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},a=i;class c extends Error{constructor(t,e){const n=a(t,e);super(n),this.name=t,this.details=e}}const s={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!==typeof registration?registration.scope:""},u=t=>[s.prefix,t,s.suffix].filter(t=>t&&t.length>0).join("-"),l=t=>{for(const e of Object.keys(s))t(e)},f={updateDetails:t=>{l(e=>{"string"===typeof t[e]&&(s[e]=t[e])})},getGoogleAnalyticsName:t=>t||u(s.googleAnalytics),getPrecacheName:t=>t||u(s.precache),getPrefix:()=>s.prefix,getRuntimeName:t=>t||u(s.runtime),getSuffix:()=>s.suffix};n("c700");let h;function p(){if(void 0===h){const e=new Response("");if("body"in e)try{new Response(e.body),h=!0}catch(t){h=!1}h=!1}return h}async function d(t,e){let n=null;if(t.url){const e=new URL(t.url);n=e.origin}if(n!==self.location.origin)throw new c("cross-origin-copy-response",{origin:n});const r=t.clone(),o={headers:new Headers(r.headers),status:r.status,statusText:r.statusText},i=e?e(o):o,a=p()?r.body:await r.blob();return new Response(a,i)}n("741b");const g={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!==typeof registration?registration.scope:""},y=t=>[g.prefix,t,g.suffix].filter(t=>t&&t.length>0).join("-"),m=t=>{for(const e of Object.keys(g))t(e)},v={updateDetails:t=>{m(e=>{"string"===typeof t[e]&&(g[e]=t[e])})},getGoogleAnalyticsName:t=>t||y(g.googleAnalytics),getPrecacheName:t=>t||y(g.precache),getPrefix:()=>g.prefix,getRuntimeName:t=>t||y(g.runtime),getSuffix:()=>g.suffix},w=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},x=w;class b extends Error{constructor(t,e){const n=x(t,e);super(n),this.name=t,this.details=e}}const _=t=>{const e=new URL(String(t),location.href);return e.href.replace(new RegExp("^"+location.origin),"")};function E(t,e){const n=new URL(t);for(const r of e)n.searchParams.delete(r);return n.href}async function R(t,e,n,r){const o=E(e.url,n);if(e.url===o)return t.match(e,r);const i={...r,ignoreSearch:!0},a=await t.keys(e,i);for(const c of a){const e=E(c.url,n);if(o===e)return t.match(c,r)}}class S{constructor(){this.promise=new Promise((t,e)=>{this.resolve=t,this.reject=e})}}const O=new Set;async function P(){for(const t of O)await t()}function N(t){return new Promise(e=>setTimeout(e,t))}n("6aa8");function k(t){return"string"===typeof t?new Request(t):t}class j{constructor(t,e){this._cacheKeys={},Object.assign(this,e),this.event=e.event,this._strategy=t,this._handlerDeferred=new S,this._extendLifetimePromises=[],this._plugins=[...t.plugins],this._pluginStateMap=new Map;for(const n of this._plugins)this._pluginStateMap.set(n,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(t){const{event:e}=this;let n=k(t);if("navigate"===n.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const r=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))n=await t({request:n.clone(),event:e})}catch(i){throw new b("plugin-error-request-will-fetch",{thrownError:i})}const o=n.clone();try{let t;t=await fetch(n,"navigate"===n.mode?void 0:this._strategy.fetchOptions);for(const n of this.iterateCallbacks("fetchDidSucceed"))t=await n({event:e,request:o,response:t});return t}catch(a){throw r&&await this.runCallbacks("fetchDidFail",{error:a,event:e,originalRequest:r.clone(),request:o.clone()}),a}}async fetchAndCachePut(t){const e=await this.fetch(t),n=e.clone();return this.waitUntil(this.cachePut(t,n)),e}async cacheMatch(t){const e=k(t);let n;const{cacheName:r,matchOptions:o}=this._strategy,i=await this.getCacheKey(e,"read"),a={...o,cacheName:r};n=await caches.match(i,a);for(const c of this.iterateCallbacks("cachedResponseWillBeUsed"))n=await c({cacheName:r,matchOptions:o,cachedResponse:n,request:i,event:this.event})||void 0;return n}async cachePut(t,e){const n=k(t);await N(0);const r=await this.getCacheKey(n,"write");if(!e)throw new b("cache-put-with-no-response",{url:_(r.url)});const o=await this._ensureResponseSafeToCache(e);if(!o)return!1;const{cacheName:i,matchOptions:a}=this._strategy,c=await self.caches.open(i),s=this.hasCallback("cacheDidUpdate"),u=s?await R(c,r.clone(),["__WB_REVISION__"],a):null;try{await c.put(r,s?o.clone():o)}catch(l){throw"QuotaExceededError"===l.name&&await P(),l}for(const f of this.iterateCallbacks("cacheDidUpdate"))await f({cacheName:i,oldResponse:u,newResponse:o.clone(),request:r,event:this.event});return!0}async getCacheKey(t,e){if(!this._cacheKeys[e]){let n=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))n=k(await t({mode:e,request:n,event:this.event,params:this.params}));this._cacheKeys[e]=n}return this._cacheKeys[e]}hasCallback(t){for(const e of this._strategy.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const n of this.iterateCallbacks(t))await n(e)}*iterateCallbacks(t){for(const e of this._strategy.plugins)if("function"===typeof e[t]){const n=this._pluginStateMap.get(e),r=r=>{const o={...r,state:n};return e[t](o)};yield r}}waitUntil(t){return this._extendLifetimePromises.push(t),t}async doneWaiting(){let t;while(t=this._extendLifetimePromises.shift())await t}destroy(){this._handlerDeferred.resolve()}async _ensureResponseSafeToCache(t){let e=t,n=!1;for(const r of this.iterateCallbacks("cacheWillUpdate"))if(e=await r({request:this.request,response:e,event:this.event})||void 0,n=!0,!e)break;return n||e&&200!==e.status&&(e=void 0),e}}class T{constructor(t={}){this.cacheName=v.getRuntimeName(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,n="string"===typeof t.request?new Request(t.request):t.request,r="params"in t?t.params:void 0,o=new j(this,{event:e,request:n,params:r}),i=this._getResponse(o,n,e),a=this._awaitComplete(i,o,n,e);return[i,a]}async _getResponse(t,e,n){await t.runCallbacks("handlerWillStart",{event:n,request:e});let r=void 0;try{if(r=await this._handle(e,t),!r||"error"===r.type)throw new b("no-response",{url:e.url})}catch(o){for(const i of t.iterateCallbacks("handlerDidError"))if(r=await i({error:o,event:n,request:e}),r)break;if(!r)throw o}for(const i of t.iterateCallbacks("handlerWillRespond"))r=await i({event:n,request:e,response:r});return r}async _awaitComplete(t,e,n,r){let o,i;try{o=await t}catch(i){}try{await e.runCallbacks("handlerDidRespond",{event:r,request:n,response:o}),await e.doneWaiting()}catch(a){i=a}if(await e.runCallbacks("handlerDidComplete",{event:r,request:n,response:o,error:i}),e.destroy(),i)throw i}}class C extends T{constructor(t={}){t.cacheName=f.getPrecacheName(t.cacheName),super(t),this._fallbackToNetwork=!1!==t.fallbackToNetwork,this.plugins.push(C.copyRedirectedCacheableResponsesPlugin)}async _handle(t,e){const n=await e.cacheMatch(t);return n||(e.event&&"install"===e.event.type?await this._handleInstall(t,e):await this._handleFetch(t,e))}async _handleFetch(t,e){let n;if(!this._fallbackToNetwork)throw new c("missing-precache-entry",{cacheName:this.cacheName,url:t.url});return n=await e.fetch(t),n}async _handleInstall(t,e){this._useDefaultCacheabilityPluginIfNeeded();const n=await e.fetch(t),r=await e.cachePut(t,n.clone());if(!r)throw new c("bad-precaching-response",{url:t.url,status:n.status});return n}_useDefaultCacheabilityPluginIfNeeded(){let t=null,e=0;for(const[n,r]of this.plugins.entries())r!==C.copyRedirectedCacheableResponsesPlugin&&(r===C.defaultPrecacheCacheabilityPlugin&&(t=n),r.cacheWillUpdate&&e++);0===e?this.plugins.push(C.defaultPrecacheCacheabilityPlugin):e>1&&null!==t&&this.plugins.splice(t,1)}}C.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:t}){return!t||t.status>=400?null:t}},C.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:t}){return t.redirected?await d(t):t}};n("95a8");const A=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},q=A;class L extends Error{constructor(t,e){const n=q(t,e);super(n),this.name=t,this.details=e}}n("e6d2");const M="GET",U=t=>t&&"object"===typeof t?t:{handle:t};class I{constructor(t,e,n=M){this.handler=U(e),this.match=t,this.method=n}setCatchHandler(t){this.catchHandler=U(t)}}class D extends I{constructor(t,e,n){const r=({url:e})=>{const n=t.exec(e.href);if(n&&(e.origin===location.origin||0===n.index))return n.slice(1)};super(r,e,n)}}class F{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener("fetch",t=>{const{request:e}=t,n=this.handleRequest({request:e,event:t});n&&t.respondWith(n)})}addCacheListener(){self.addEventListener("message",t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data;0;const n=Promise.all(e.urlsToCache.map(e=>{"string"===typeof e&&(e=[e]);const n=new Request(...e);return this.handleRequest({request:n,event:t})}));t.waitUntil(n),t.ports&&t.ports[0]&&n.then(()=>t.ports[0].postMessage(!0))}})}handleRequest({request:t,event:e}){const n=new URL(t.url,location.href);if(!n.protocol.startsWith("http"))return void 0;const r=n.origin===location.origin,{params:o,route:i}=this.findMatchingRoute({event:e,request:t,sameOrigin:r,url:n});let a=i&&i.handler;const c=t.method;if(!a&&this._defaultHandlerMap.has(c)&&(a=this._defaultHandlerMap.get(c)),!a)return void 0;let s;try{s=a.handle({url:n,request:t,event:e,params:o})}catch(l){s=Promise.reject(l)}const u=i&&i.catchHandler;return s instanceof Promise&&(this._catchHandler||u)&&(s=s.catch(async r=>{if(u){0;try{return await u.handle({url:n,request:t,event:e,params:o})}catch(i){r=i}}if(this._catchHandler)return this._catchHandler.handle({url:n,request:t,event:e});throw r})),s}findMatchingRoute({url:t,sameOrigin:e,request:n,event:r}){const o=this._routes.get(n.method)||[];for(const i of o){let o;const a=i.match({url:t,sameOrigin:e,request:n,event:r});if(a)return o=a,(Array.isArray(a)&&0===a.length||a.constructor===Object&&0===Object.keys(a).length||"boolean"===typeof a)&&(o=void 0),{route:i,params:o}}return{}}setDefaultHandler(t,e=M){this._defaultHandlerMap.set(e,U(t))}setCatchHandler(t){this._catchHandler=U(t)}registerRoute(t){this._routes.has(t.method)||this._routes.set(t.method,[]),this._routes.get(t.method).push(t)}unregisterRoute(t){if(!this._routes.has(t.method))throw new L("unregister-route-but-not-found-with-method",{method:t.method});const e=this._routes.get(t.method).indexOf(t);if(!(e>-1))throw new L("unregister-route-route-not-registered");this._routes.get(t.method).splice(e,1)}}let W;const H=()=>(W||(W=new F,W.addFetchListener(),W.addCacheListener()),W);function K(t,e,n){let r;if("string"===typeof t){const o=new URL(t,location.href);0;const i=({url:t})=>t.href===o.href;r=new I(i,e,n)}else if(t instanceof RegExp)r=new D(t,e,n);else if("function"===typeof t)r=new I(t,e,n);else{if(!(t instanceof I))throw new L("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});r=t}const o=H();return o.registerRoute(r),r}function G(t){const e=H();e.setCatchHandler(t)}class B extends T{async _handle(t,e){let n,r=await e.cacheMatch(t);if(r)0;else{0;try{r=await e.fetchAndCachePut(t)}catch(o){n=o}0}if(!r)throw new b("no-response",{url:t.url,error:n});return r}}const Y={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null};class $ extends T{constructor(t={}){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(Y),this._networkTimeoutSeconds=t.networkTimeoutSeconds||0}async _handle(t,e){const n=[];const r=[];let o;if(this._networkTimeoutSeconds){const{id:i,promise:a}=this._getTimeoutPromise({request:t,logs:n,handler:e});o=i,r.push(a)}const i=this._getNetworkPromise({timeoutId:o,request:t,logs:n,handler:e});r.push(i);const a=await e.waitUntil((async()=>await e.waitUntil(Promise.race(r))||await i)());if(!a)throw new b("no-response",{url:t.url});return a}_getTimeoutPromise({request:t,logs:e,handler:n}){let r;const o=new Promise(e=>{const o=async()=>{e(await n.cacheMatch(t))};r=setTimeout(o,1e3*this._networkTimeoutSeconds)});return{promise:o,id:r}}async _getNetworkPromise({timeoutId:t,request:e,logs:n,handler:r}){let o,i;try{i=await r.fetchAndCachePut(e)}catch(a){o=a}return t&&clearTimeout(t),!o&&i||(i=await r.cacheMatch(e)),i}}class z extends T{constructor(t){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(Y)}async _handle(t,e){const n=e.fetchAndCachePut(t).catch(()=>{});let r,o=await e.cacheMatch(t);if(o)0;else{0;try{o=await n}catch(i){r=i}}if(!o)throw new b("no-response",{url:t.url,error:r});return o}}n("d2e2");const J=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},Q=J;class V extends Error{constructor(t,e){const n=Q(t,e);super(n),this.name=t,this.details=e}}function X(t){t.then(()=>{})}class Z{constructor(t,e,{onupgradeneeded:n,onversionchange:r}={}){this._db=null,this._name=t,this._version=e,this._onupgradeneeded=n,this._onversionchange=r||(()=>this.close())}get db(){return this._db}async open(){if(!this._db)return this._db=await new Promise((t,e)=>{let n=!1;setTimeout(()=>{n=!0,e(new Error("The open request was blocked and timed out"))},this.OPEN_TIMEOUT);const r=indexedDB.open(this._name,this._version);r.onerror=()=>e(r.error),r.onupgradeneeded=t=>{n?(r.transaction.abort(),r.result.close()):"function"===typeof this._onupgradeneeded&&this._onupgradeneeded(t)},r.onsuccess=()=>{const e=r.result;n?e.close():(e.onversionchange=this._onversionchange.bind(this),t(e))}}),this}async getKey(t,e){return(await this.getAllKeys(t,e,1))[0]}async getAll(t,e,n){return await this.getAllMatching(t,{query:e,count:n})}async getAllKeys(t,e,n){const r=await this.getAllMatching(t,{query:e,count:n,includeKeys:!0});return r.map(t=>t.key)}async getAllMatching(t,{index:e,query:n=null,direction:r="next",count:o,includeKeys:i=!1}={}){return await this.transaction([t],"readonly",(a,c)=>{const s=a.objectStore(t),u=e?s.index(e):s,l=[],f=u.openCursor(n,r);f.onsuccess=()=>{const t=f.result;t?(l.push(i?t:t.value),o&&l.length>=o?c(l):t.continue()):c(l)}})}async transaction(t,e,n){return await this.open(),await new Promise((r,o)=>{const i=this._db.transaction(t,e);i.onabort=()=>o(i.error),i.oncomplete=()=>r(),n(i,t=>r(t))})}async _call(t,e,n,...r){const o=(n,o)=>{const i=n.objectStore(e),a=i[t].apply(i,r);a.onsuccess=()=>o(a.result)};return await this.transaction([e],n,o)}close(){this._db&&(this._db.close(),this._db=null)}}Z.prototype.OPEN_TIMEOUT=2e3;const tt={readonly:["get","count","getKey","getAll","getAllKeys"],readwrite:["add","put","clear","delete"]};for(const[yt,mt]of Object.entries(tt))for(const t of mt)t in IDBObjectStore.prototype&&(Z.prototype[t]=async function(e,...n){return await this._call(t,e,yt,...n)});const et=async t=>{await new Promise((e,n)=>{const r=indexedDB.deleteDatabase(t);r.onerror=()=>{n(r.error)},r.onblocked=()=>{n(new Error("Delete blocked"))},r.onsuccess=()=>{e()}})};n("d8a5");const nt="workbox-expiration",rt="cache-entries",ot=t=>{const e=new URL(t,location.href);return e.hash="",e.href};class it{constructor(t){this._cacheName=t,this._db=new Z(nt,1,{onupgradeneeded:t=>this._handleUpgrade(t)})}_handleUpgrade(t){const e=t.target.result,n=e.createObjectStore(rt,{keyPath:"id"});n.createIndex("cacheName","cacheName",{unique:!1}),n.createIndex("timestamp","timestamp",{unique:!1}),et(this._cacheName)}async setTimestamp(t,e){t=ot(t);const n={url:t,timestamp:e,cacheName:this._cacheName,id:this._getId(t)};await this._db.put(rt,n)}async getTimestamp(t){const e=await this._db.get(rt,this._getId(t));return e.timestamp}async expireEntries(t,e){const n=await this._db.transaction(rt,"readwrite",(n,r)=>{const o=n.objectStore(rt),i=o.index("timestamp").openCursor(null,"prev"),a=[];let c=0;i.onsuccess=()=>{const n=i.result;if(n){const r=n.value;r.cacheName===this._cacheName&&(t&&r.timestamp=e?a.push(n.value):c++),n.continue()}else r(a)}}),r=[];for(const o of n)await this._db.delete(rt,o.id),r.push(o.url);return r}_getId(t){return this._cacheName+"|"+ot(t)}}class at{constructor(t,e={}){this._isRunning=!1,this._rerunRequested=!1,this._maxEntries=e.maxEntries,this._maxAgeSeconds=e.maxAgeSeconds,this._matchOptions=e.matchOptions,this._cacheName=t,this._timestampModel=new it(t)}async expireEntries(){if(this._isRunning)return void(this._rerunRequested=!0);this._isRunning=!0;const t=this._maxAgeSeconds?Date.now()-1e3*this._maxAgeSeconds:0,e=await this._timestampModel.expireEntries(t,this._maxEntries),n=await self.caches.open(this._cacheName);for(const r of e)await n.delete(r,this._matchOptions);this._isRunning=!1,this._rerunRequested&&(this._rerunRequested=!1,X(this.expireEntries()))}async updateTimestamp(t){await this._timestampModel.setTimestamp(t,Date.now())}async isURLExpired(t){if(this._maxAgeSeconds){const e=await this._timestampModel.getTimestamp(t),n=Date.now()-1e3*this._maxAgeSeconds;return e[ct.prefix,t,ct.suffix].filter(t=>t&&t.length>0).join("-"),ut=t=>{for(const e of Object.keys(ct))t(e)},lt={updateDetails:t=>{ut(e=>{"string"===typeof t[e]&&(ct[e]=t[e])})},getGoogleAnalyticsName:t=>t||st(ct.googleAnalytics),getPrecacheName:t=>t||st(ct.precache),getPrefix:()=>ct.prefix,getRuntimeName:t=>t||st(ct.runtime),getSuffix:()=>ct.suffix},ft=new Set;function ht(t){ft.add(t)}class pt{constructor(t={}){this.cachedResponseWillBeUsed=async({event:t,request:e,cacheName:n,cachedResponse:r})=>{if(!r)return null;const o=this._isResponseDateFresh(r),i=this._getCacheExpiration(n);X(i.expireEntries());const a=i.updateTimestamp(e.url);if(t)try{t.waitUntil(a)}catch(c){0}return o?r:null},this.cacheDidUpdate=async({cacheName:t,request:e})=>{const n=this._getCacheExpiration(t);await n.updateTimestamp(e.url),await n.expireEntries()},this._config=t,this._maxAgeSeconds=t.maxAgeSeconds,this._cacheExpirations=new Map,t.purgeOnQuotaError&&ht(()=>this.deleteCacheAndMetadata())}_getCacheExpiration(t){if(t===lt.getRuntimeName())throw new V("expire-custom-caches-only");let e=this._cacheExpirations.get(t);return e||(e=new at(t,this._config),this._cacheExpirations.set(t,e)),e}_isResponseDateFresh(t){if(!this._maxAgeSeconds)return!0;const e=this._getDateHeaderTimestamp(t);if(null===e)return!0;const n=Date.now();return e>=n-1e3*this._maxAgeSeconds}_getDateHeaderTimestamp(t){if(!t.headers.has("date"))return null;const e=t.headers.get("date"),n=new Date(e),r=n.getTime();return isNaN(r)?null:r}async deleteCacheAndMetadata(){for(const[t,e]of this._cacheExpirations)await self.caches.delete(t),await e.delete();this._cacheExpirations=new Map}}var dt="offline-html",gt="/offline/";self.addEventListener("install",function(){var t=o(regeneratorRuntime.mark((function t(e){return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:e.waitUntil(caches.open(dt).then((function(t){return t.add(new Request(gt,{cache:"reload"}))})));case 1:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}()),[{'url':'static/vue/css/chunk-vendors.css'},{'url':'static/vue/js/chunk-vendors.js'},{'url':'static/vue/js/offline_view.js'},{'url':'static/vue/js/recipe_view.js'},{'url':'static/vue/manifest.json'},{'url':'static/vue/offline_view.html'},{'url':'static/vue/recipe_view.html'}],G((function(t){var e=t.event;switch(e.request.destination){case"document":return console.log("Triggered fallback HTML"),caches.open(dt).then((function(t){return t.match(gt)}));default:return console.log("Triggered response ERROR"),Response.error()}})),K((function(t){var e=t.request;return"image"===e.destination}),new B({cacheName:"images",plugins:[new pt({maxEntries:20})]})),K((function(t){var e=t.request;return"script"===e.destination||"style"===e.destination}),new z({cacheName:"assets"})),K(new RegExp("jsreverse"),new z({cacheName:"assets"})),K(new RegExp("jsi18n"),new z({cacheName:"assets"})),K(new RegExp("api/recipe/([0-9]+)"),new $({cacheName:"api-recipe",plugins:[new pt({maxEntries:50})]})),K(new RegExp("api/*"),new $({cacheName:"api",plugins:[new pt({maxEntries:50})]})),K((function(t){var e=t.request;return"document"===e.destination}),new $({cacheName:"html",plugins:[new pt({maxAgeSeconds:2592e3,maxEntries:50})]}))},"25f0":function(t,e,n){"use strict";var r=n("6eeb"),o=n("825a"),i=n("d039"),a=n("ad6d"),c="toString",s=RegExp.prototype,u=s[c],l=i((function(){return"/a/b"!=u.call({source:"a",flags:"b"})})),f=u.name!=c;(l||f)&&r(RegExp.prototype,c,(function(){var t=o(this),e=String(t.source),n=t.flags,r=String(void 0===n&&t instanceof RegExp&&!("flags"in s)?a.call(t):n);return"/"+e+"/"+r}),{unsafe:!0})},2626:function(t,e,n){"use strict";var r=n("d066"),o=n("9bf2"),i=n("b622"),a=n("83ab"),c=i("species");t.exports=function(t){var e=r(t),n=o.f;a&&e&&!e[c]&&n(e,c,{configurable:!0,get:function(){return this}})}},"2d00":function(t,e,n){var r,o,i=n("da84"),a=n("342f"),c=i.process,s=c&&c.versions,u=s&&s.v8;u?(r=u.split("."),o=r[0]+r[1]):a&&(r=a.match(/Edge\/(\d+)/),(!r||r[1]>=74)&&(r=a.match(/Chrome\/(\d+)/),r&&(o=r[1]))),t.exports=o&&+o},"342f":function(t,e,n){var r=n("d066");t.exports=r("navigator","userAgent")||""},"3bbe":function(t,e,n){var r=n("861d");t.exports=function(t){if(!r(t)&&null!==t)throw TypeError("Can't set "+String(t)+" as a prototype");return t}},"40b9":function(t,e,n){"use strict";try{self["workbox:core:6.1.2"]&&_()}catch(r){}},"428f":function(t,e,n){var r=n("da84");t.exports=r},"44ad":function(t,e,n){var r=n("d039"),o=n("c6b6"),i="".split;t.exports=r((function(){return!Object("z").propertyIsEnumerable(0)}))?function(t){return"String"==o(t)?i.call(t,""):Object(t)}:Object},"44e7":function(t,e,n){var r=n("861d"),o=n("c6b6"),i=n("b622"),a=i("match");t.exports=function(t){var e;return r(t)&&(void 0!==(e=t[a])?!!e:"RegExp"==o(t))}},"466d":function(t,e,n){"use strict";var r=n("d784"),o=n("825a"),i=n("50c4"),a=n("1d80"),c=n("8aa5"),s=n("14c3");r("match",1,(function(t,e,n){return[function(e){var n=a(this),r=void 0==e?void 0:e[t];return void 0!==r?r.call(e,n):new RegExp(e)[t](String(n))},function(t){var r=n(e,t,this);if(r.done)return r.value;var a=o(t),u=String(this);if(!a.global)return s(a,u);var l=a.unicode;a.lastIndex=0;var f,h=[],p=0;while(null!==(f=s(a,u))){var d=String(f[0]);h[p]=d,""===d&&(a.lastIndex=c(u,i(a.lastIndex),l)),p++}return 0===p?null:h}]}))},4930:function(t,e,n){var r=n("605d"),o=n("2d00"),i=n("d039");t.exports=!!Object.getOwnPropertySymbols&&!i((function(){return!Symbol.sham&&(r?38===o:o>37&&o<41)}))},"4d63":function(t,e,n){var r=n("83ab"),o=n("da84"),i=n("94ca"),a=n("7156"),c=n("9bf2").f,s=n("241c").f,u=n("44e7"),l=n("ad6d"),f=n("9f7f"),h=n("6eeb"),p=n("d039"),d=n("69f3").set,g=n("2626"),y=n("b622"),m=y("match"),v=o.RegExp,w=v.prototype,x=/a/g,b=/a/g,_=new v(x)!==x,E=f.UNSUPPORTED_Y,R=r&&i("RegExp",!_||E||p((function(){return b[m]=!1,v(x)!=x||v(b)==b||"/a/i"!=v(x,"i")})));if(R){var S=function(t,e){var n,r=this instanceof S,o=u(t),i=void 0===e;if(!r&&o&&t.constructor===S&&i)return t;_?o&&!i&&(t=t.source):t instanceof S&&(i&&(e=l.call(t)),t=t.source),E&&(n=!!e&&e.indexOf("y")>-1,n&&(e=e.replace(/y/g,"")));var c=a(_?new v(t,e):v(t,e),r?this:w,S);return E&&n&&d(c,{sticky:n}),c},O=function(t){t in S||c(S,t,{configurable:!0,get:function(){return v[t]},set:function(e){v[t]=e}})},P=s(v),N=0;while(P.length>N)O(P[N++]);w.constructor=S,S.prototype=w,h(o,"RegExp",S)}g("RegExp")},"4d64":function(t,e,n){var r=n("fc6a"),o=n("50c4"),i=n("23cb"),a=function(t){return function(e,n,a){var c,s=r(e),u=o(s.length),l=i(a,u);if(t&&n!=n){while(u>l)if(c=s[l++],c!=c)return!0}else for(;u>l;l++)if((t||l in s)&&s[l]===n)return t||l||0;return!t&&-1}};t.exports={includes:a(!0),indexOf:a(!1)}},"50c4":function(t,e,n){var r=n("a691"),o=Math.min;t.exports=function(t){return t>0?o(r(t),9007199254740991):0}},5135:function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},5692:function(t,e,n){var r=n("c430"),o=n("c6cd");(t.exports=function(t,e){return o[t]||(o[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.9.1",mode:r?"pure":"global",copyright:"© 2021 Denis Pushkarev (zloirock.ru)"})},"56ef":function(t,e,n){var r=n("d066"),o=n("241c"),i=n("7418"),a=n("825a");t.exports=r("Reflect","ownKeys")||function(t){var e=o.f(a(t)),n=i.f;return n?e.concat(n(t)):e}},"5c6c":function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},"605d":function(t,e,n){var r=n("c6b6"),o=n("da84");t.exports="process"==r(o.process)},6547:function(t,e,n){var r=n("a691"),o=n("1d80"),i=function(t){return function(e,n){var i,a,c=String(o(e)),s=r(n),u=c.length;return s<0||s>=u?t?"":void 0:(i=c.charCodeAt(s),i<55296||i>56319||s+1===u||(a=c.charCodeAt(s+1))<56320||a>57343?t?c.charAt(s):i:t?c.slice(s,s+2):a-56320+(i-55296<<10)+65536)}};t.exports={codeAt:i(!1),charAt:i(!0)}},"69f3":function(t,e,n){var r,o,i,a=n("7f9a"),c=n("da84"),s=n("861d"),u=n("9112"),l=n("5135"),f=n("c6cd"),h=n("f772"),p=n("d012"),d=c.WeakMap,g=function(t){return i(t)?o(t):r(t,{})},y=function(t){return function(e){var n;if(!s(e)||(n=o(e)).type!==t)throw TypeError("Incompatible receiver, "+t+" required");return n}};if(a){var m=f.state||(f.state=new d),v=m.get,w=m.has,x=m.set;r=function(t,e){return e.facade=t,x.call(m,t,e),e},o=function(t){return v.call(m,t)||{}},i=function(t){return w.call(m,t)}}else{var b=h("state");p[b]=!0,r=function(t,e){return e.facade=t,u(t,b,e),e},o=function(t){return l(t,b)?t[b]:{}},i=function(t){return l(t,b)}}t.exports={set:r,get:o,has:i,enforce:g,getterFor:y}},"6aa8":function(t,e,n){"use strict";try{self["workbox:strategies:6.1.2"]&&_()}catch(r){}},"6eeb":function(t,e,n){var r=n("da84"),o=n("9112"),i=n("5135"),a=n("ce4e"),c=n("8925"),s=n("69f3"),u=s.get,l=s.enforce,f=String(String).split("String");(t.exports=function(t,e,n,c){var s,u=!!c&&!!c.unsafe,h=!!c&&!!c.enumerable,p=!!c&&!!c.noTargetGet;"function"==typeof n&&("string"!=typeof e||i(n,"name")||o(n,"name",e),s=l(n),s.source||(s.source=f.join("string"==typeof e?e:""))),t!==r?(u?!p&&t[e]&&(h=!0):delete t[e],h?t[e]=n:o(t,e,n)):h?t[e]=n:a(e,n)})(Function.prototype,"toString",(function(){return"function"==typeof this&&u(this).source||c(this)}))},7156:function(t,e,n){var r=n("861d"),o=n("d2bb");t.exports=function(t,e,n){var i,a;return o&&"function"==typeof(i=e.constructor)&&i!==n&&r(a=i.prototype)&&a!==n.prototype&&o(t,a),t}},7418:function(t,e){e.f=Object.getOwnPropertySymbols},"741b":function(t,e,n){"use strict";try{self["workbox:core:6.1.2"]&&_()}catch(r){}},7839:function(t,e){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},"7f9a":function(t,e,n){var r=n("da84"),o=n("8925"),i=r.WeakMap;t.exports="function"===typeof i&&/native code/.test(o(i))},"825a":function(t,e,n){var r=n("861d");t.exports=function(t){if(!r(t))throw TypeError(String(t)+" is not an object");return t}},"83ab":function(t,e,n){var r=n("d039");t.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},"861d":function(t,e){t.exports=function(t){return"object"===typeof t?null!==t:"function"===typeof t}},8925:function(t,e,n){var r=n("c6cd"),o=Function.toString;"function"!=typeof r.inspectSource&&(r.inspectSource=function(t){return o.call(t)}),t.exports=r.inspectSource},"8aa5":function(t,e,n){"use strict";var r=n("6547").charAt;t.exports=function(t,e,n){return e+(n?r(t,e).length:1)}},"90e3":function(t,e){var n=0,r=Math.random();t.exports=function(t){return"Symbol("+String(void 0===t?"":t)+")_"+(++n+r).toString(36)}},9112:function(t,e,n){var r=n("83ab"),o=n("9bf2"),i=n("5c6c");t.exports=r?function(t,e,n){return o.f(t,e,i(1,n))}:function(t,e,n){return t[e]=n,t}},9263:function(t,e,n){"use strict";var r=n("ad6d"),o=n("9f7f"),i=RegExp.prototype.exec,a=String.prototype.replace,c=i,s=function(){var t=/a/,e=/b*/g;return i.call(t,"a"),i.call(e,"a"),0!==t.lastIndex||0!==e.lastIndex}(),u=o.UNSUPPORTED_Y||o.BROKEN_CARET,l=void 0!==/()??/.exec("")[1],f=s||l||u;f&&(c=function(t){var e,n,o,c,f=this,h=u&&f.sticky,p=r.call(f),d=f.source,g=0,y=t;return h&&(p=p.replace("y",""),-1===p.indexOf("g")&&(p+="g"),y=String(t).slice(f.lastIndex),f.lastIndex>0&&(!f.multiline||f.multiline&&"\n"!==t[f.lastIndex-1])&&(d="(?: "+d+")",y=" "+y,g++),n=new RegExp("^(?:"+d+")",p)),l&&(n=new RegExp("^"+d+"$(?!\\s)",p)),s&&(e=f.lastIndex),o=i.call(h?n:f,y),h?o?(o.input=o.input.slice(g),o[0]=o[0].slice(g),o.index=f.lastIndex,f.lastIndex+=o[0].length):f.lastIndex=0:s&&o&&(f.lastIndex=f.global?o.index+o[0].length:e),l&&o&&o.length>1&&a.call(o[0],n,(function(){for(c=1;c=0;--i){var a=this.tryEntries[i],c=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var s=r.call(a,"catchLoc"),u=r.call(a,"finallyLoc");if(s&&u){if(this.prev=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&r.call(o,"finallyLoc")&&this.prev=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),N(n),g}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var r=n.completion;if("throw"===r.type){var o=r.arg;N(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,n,r){return this.delegate={iterator:j(t),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=e),g}},t}(t.exports);try{regeneratorRuntime=r}catch(o){Function("r","regeneratorRuntime = r")(r)}},"9bf2":function(t,e,n){var r=n("83ab"),o=n("0cfb"),i=n("825a"),a=n("c04e"),c=Object.defineProperty;e.f=r?c:function(t,e,n){if(i(t),e=a(e,!0),i(n),o)try{return c(t,e,n)}catch(r){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(t[e]=n.value),t}},"9f7f":function(t,e,n){"use strict";var r=n("d039");function o(t,e){return RegExp(t,e)}e.UNSUPPORTED_Y=r((function(){var t=o("a","y");return t.lastIndex=2,null!=t.exec("abcd")})),e.BROKEN_CARET=r((function(){var t=o("^r","gy");return t.lastIndex=2,null!=t.exec("str")}))},a691:function(t,e){var n=Math.ceil,r=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?r:n)(t)}},ac1f:function(t,e,n){"use strict";var r=n("23e7"),o=n("9263");r({target:"RegExp",proto:!0,forced:/./.exec!==o},{exec:o})},ad6d:function(t,e,n){"use strict";var r=n("825a");t.exports=function(){var t=r(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.dotAll&&(e+="s"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},b041:function(t,e,n){"use strict";var r=n("00ee"),o=n("f5df");t.exports=r?{}.toString:function(){return"[object "+o(this)+"]"}},b622:function(t,e,n){var r=n("da84"),o=n("5692"),i=n("5135"),a=n("90e3"),c=n("4930"),s=n("fdbf"),u=o("wks"),l=r.Symbol,f=s?l:l&&l.withoutSetter||a;t.exports=function(t){return i(u,t)&&(c||"string"==typeof u[t])||(c&&i(l,t)?u[t]=l[t]:u[t]=f("Symbol."+t)),u[t]}},c04e:function(t,e,n){var r=n("861d");t.exports=function(t,e){if(!r(t))return t;var n,o;if(e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;if("function"==typeof(n=t.valueOf)&&!r(o=n.call(t)))return o;if(!e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;throw TypeError("Can't convert object to primitive value")}},c430:function(t,e){t.exports=!1},c6b6:function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},c6cd:function(t,e,n){var r=n("da84"),o=n("ce4e"),i="__core-js_shared__",a=r[i]||o(i,{});t.exports=a},c700:function(t,e,n){"use strict";try{self["workbox:precaching:6.1.2"]&&_()}catch(r){}},c8ba:function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(r){"object"===typeof window&&(n=window)}t.exports=n},ca84:function(t,e,n){var r=n("5135"),o=n("fc6a"),i=n("4d64").indexOf,a=n("d012");t.exports=function(t,e){var n,c=o(t),s=0,u=[];for(n in c)!r(a,n)&&r(c,n)&&u.push(n);while(e.length>s)r(c,n=e[s++])&&(~i(u,n)||u.push(n));return u}},cc12:function(t,e,n){var r=n("da84"),o=n("861d"),i=r.document,a=o(i)&&o(i.createElement);t.exports=function(t){return a?i.createElement(t):{}}},ce4e:function(t,e,n){var r=n("da84"),o=n("9112");t.exports=function(t,e){try{o(r,t,e)}catch(n){r[t]=e}return e}},d012:function(t,e){t.exports={}},d039:function(t,e){t.exports=function(t){try{return!!t()}catch(e){return!0}}},d066:function(t,e,n){var r=n("428f"),o=n("da84"),i=function(t){return"function"==typeof t?t:void 0};t.exports=function(t,e){return arguments.length<2?i(r[t])||i(o[t]):r[t]&&r[t][e]||o[t]&&o[t][e]}},d1e7:function(t,e,n){"use strict";var r={}.propertyIsEnumerable,o=Object.getOwnPropertyDescriptor,i=o&&!r.call({1:2},1);e.f=i?function(t){var e=o(this,t);return!!e&&e.enumerable}:r},d2bb:function(t,e,n){var r=n("825a"),o=n("3bbe");t.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,n={};try{t=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set,t.call(n,[]),e=n instanceof Array}catch(i){}return function(n,i){return r(n),o(i),e?t.call(n,i):n.__proto__=i,n}}():void 0)},d2e2:function(t,e,n){"use strict";try{self["workbox:core:6.1.2"]&&_()}catch(r){}},d3b7:function(t,e,n){var r=n("00ee"),o=n("6eeb"),i=n("b041");r||o(Object.prototype,"toString",i,{unsafe:!0})},d784:function(t,e,n){"use strict";n("ac1f");var r=n("6eeb"),o=n("d039"),i=n("b622"),a=n("9263"),c=n("9112"),s=i("species"),u=!o((function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")})),l=function(){return"$0"==="a".replace(/./,"$0")}(),f=i("replace"),h=function(){return!!/./[f]&&""===/./[f]("a","$0")}(),p=!o((function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var n="ab".split(t);return 2!==n.length||"a"!==n[0]||"b"!==n[1]}));t.exports=function(t,e,n,f){var d=i(t),g=!o((function(){var e={};return e[d]=function(){return 7},7!=""[t](e)})),y=g&&!o((function(){var e=!1,n=/a/;return"split"===t&&(n={},n.constructor={},n.constructor[s]=function(){return n},n.flags="",n[d]=/./[d]),n.exec=function(){return e=!0,null},n[d](""),!e}));if(!g||!y||"replace"===t&&(!u||!l||h)||"split"===t&&!p){var m=/./[d],v=n(d,""[t],(function(t,e,n,r,o){return e.exec===a?g&&!o?{done:!0,value:m.call(e,n,r)}:{done:!0,value:t.call(n,e,r)}:{done:!1}}),{REPLACE_KEEPS_$0:l,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:h}),w=v[0],x=v[1];r(String.prototype,t,w),r(RegExp.prototype,d,2==e?function(t,e){return x.call(t,this,e)}:function(t){return x.call(t,this)})}f&&c(RegExp.prototype[d],"sham",!0)}},d8a5:function(t,e,n){"use strict";try{self["workbox:expiration:6.1.2"]&&_()}catch(r){}},da84:function(t,e,n){(function(e){var n=function(t){return t&&t.Math==Math&&t};t.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof e&&e)||function(){return this}()||Function("return this")()}).call(this,n("c8ba"))},e6d2:function(t,e,n){"use strict";try{self["workbox:routing:6.1.2"]&&_()}catch(r){}},e893:function(t,e,n){var r=n("5135"),o=n("56ef"),i=n("06cf"),a=n("9bf2");t.exports=function(t,e){for(var n=o(e),c=a.f,s=i.f,u=0;u=4.5.3 <5.0.0": - version "4.5.3" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.3.tgz#c6a72b355aaf323920be800246a6e4ef30997fe6" - integrity sha512-o9ppKQioXGqhw8Z7mah6KdTYpNQY//tipnkxppWhPbiSWdD+1raYsnhwEZjkTHYbGee4cVQ0Rx65EhOY/HNLcQ== + version "4.6.0" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.6.0.tgz#97b9f29ac98f98dfa43bf7468262d84392552fd7" + integrity sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw== brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0= + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" braces@^2.3.1, braces@^2.3.2: version "2.3.2" - resolved "https://registry.npm.taobao.org/braces/download/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha1-WXn9PxTNUxVl5fot8av/8d+u5yk= + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -2155,22 +2183,22 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" -braces@~3.0.2: +braces@^3.0.1, braces@~3.0.2: version "3.0.2" - resolved "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha1-NFThpGLujVmeI23zNs2epPiv4Qc= + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" -brorand@^1.0.1: +brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/brorand/download/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" - resolved "https://registry.npm.taobao.org/browserify-aes/download/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha1-Mmc0ZC9APavDADIJhTu3CtQo70g= + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -2181,8 +2209,8 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: browserify-cipher@^1.0.0: version "1.0.1" - resolved "https://registry.npm.taobao.org/browserify-cipher/download/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha1-jWR0wbhwv9q807z8wZNKEOlPFfA= + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" browserify-des "^1.0.0" @@ -2190,8 +2218,8 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" - resolved "https://registry.npm.taobao.org/browserify-des/download/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw= + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" des.js "^1.0.0" @@ -2200,16 +2228,16 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: version "4.1.0" - resolved "https://registry.npm.taobao.org/browserify-rsa/download/browserify-rsa-4.1.0.tgz?cache=0&sync_timestamp=1605194217709&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrowserify-rsa%2Fdownload%2Fbrowserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha1-sv0Gtbda4pf3zi3GUfkY9b4VjI0= + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== dependencies: bn.js "^5.0.0" randombytes "^2.0.1" browserify-sign@^4.0.0: version "4.2.1" - resolved "https://registry.npm.taobao.org/browserify-sign/download/browserify-sign-4.2.1.tgz?cache=0&sync_timestamp=1596557777983&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrowserify-sign%2Fdownload%2Fbrowserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha1-6vSt1G3VS+O7OzbAzxWrvrp5VsM= + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== dependencies: bn.js "^5.1.1" browserify-rsa "^4.0.1" @@ -2223,46 +2251,46 @@ browserify-sign@^4.0.0: browserify-zlib@^0.2.0: version "0.2.0" - resolved "https://registry.npm.taobao.org/browserify-zlib/download/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha1-KGlFnZqjviRf6P4sofRuLn9U1z8= + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.0: - version "4.16.1" - resolved "https://registry.npm.taobao.org/browserslist/download/browserslist-4.16.1.tgz?cache=0&sync_timestamp=1609895802866&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrowserslist%2Fdownload%2Fbrowserslist-4.16.1.tgz#bf757a2da376b3447b800a16f0f1c96358138766" - integrity sha1-v3V6LaN2s0R7gAoW8PHJY1gTh2Y= +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.3: + version "4.16.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717" + integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw== dependencies: - caniuse-lite "^1.0.30001173" + caniuse-lite "^1.0.30001181" colorette "^1.2.1" - electron-to-chromium "^1.3.634" + electron-to-chromium "^1.3.649" escalade "^3.1.1" - node-releases "^1.1.69" + node-releases "^1.1.70" buffer-from@^1.0.0: version "1.1.1" - resolved "https://registry.npm.taobao.org/buffer-from/download/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8= + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== buffer-indexof@^1.0.0: version "1.1.1" - resolved "https://registry.npm.taobao.org/buffer-indexof/download/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha1-Uvq8xqYG0aADAoAmSO9o9jnaJow= + resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" + integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== buffer-json@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/buffer-json/download/buffer-json-2.0.0.tgz#f73e13b1e42f196fe2fd67d001c7d7107edd7c23" - integrity sha1-9z4TseQvGW/i/WfQAcfXEH7dfCM= + resolved "https://registry.yarnpkg.com/buffer-json/-/buffer-json-2.0.0.tgz#f73e13b1e42f196fe2fd67d001c7d7107edd7c23" + integrity sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw== buffer-xor@^1.0.3: version "1.0.3" - resolved "https://registry.npm.taobao.org/buffer-xor/download/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^4.3.0: version "4.9.2" - resolved "https://registry.npm.taobao.org/buffer/download/buffer-4.9.2.tgz?cache=0&sync_timestamp=1606098075542&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbuffer%2Fdownload%2Fbuffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha1-Iw6tNEACmIZEhBqwJEr4xEu+Pvg= + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -2275,23 +2303,23 @@ builtin-modules@^3.1.0: builtin-status-codes@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/builtin-status-codes/download/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= bytes@3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= bytes@3.1.0: version "3.1.0" - resolved "https://registry.npm.taobao.org/bytes/download/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY= + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== cacache@^12.0.2, cacache@^12.0.3: version "12.0.4" - resolved "https://registry.npm.taobao.org/cacache/download/cacache-12.0.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcacache%2Fdownload%2Fcacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" - integrity sha1-ZovL0QWutfHZL+JVcOyVJcj6pAw= + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" + integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== dependencies: bluebird "^3.5.5" chownr "^1.1.1" @@ -2311,8 +2339,8 @@ cacache@^12.0.2, cacache@^12.0.3: cacache@^13.0.1: version "13.0.1" - resolved "https://registry.npm.taobao.org/cacache/download/cacache-13.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcacache%2Fdownload%2Fcacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c" - integrity sha1-qAAMIWlwiQgvhSh6GuxuOCAkpxw= + resolved "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c" + integrity sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w== dependencies: chownr "^1.1.2" figgy-pudding "^3.5.1" @@ -2335,8 +2363,8 @@ cacache@^13.0.1: cache-base@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/cache-base/download/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha1-Cn9GQWgxyLZi7jb+TnxZ129marI= + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" @@ -2350,8 +2378,8 @@ cache-base@^1.0.1: cache-loader@^4.1.0: version "4.1.0" - resolved "https://registry.npm.taobao.org/cache-loader/download/cache-loader-4.1.0.tgz#9948cae353aec0a1fcb1eafda2300816ec85387e" - integrity sha1-mUjK41OuwKH8ser9ojAIFuyFOH4= + resolved "https://registry.yarnpkg.com/cache-loader/-/cache-loader-4.1.0.tgz#9948cae353aec0a1fcb1eafda2300816ec85387e" + integrity sha512-ftOayxve0PwKzBF/GLsZNC9fJBXl8lkZE3TOsjkboHfVHVkL39iUEs1FO07A33mizmci5Dudt38UZrrYXDtbhw== dependencies: buffer-json "^2.0.0" find-cache-dir "^3.0.0" @@ -2360,46 +2388,46 @@ cache-loader@^4.1.0: neo-async "^2.6.1" schema-utils "^2.0.0" -call-bind@^1.0.0: - version "1.0.0" - resolved "https://registry.npm.taobao.org/call-bind/download/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" - integrity sha1-JBJwVLs/m9y0sfuCQYGGBy93uM4= +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== dependencies: function-bind "^1.1.1" - get-intrinsic "^1.0.0" + get-intrinsic "^1.0.2" call-me-maybe@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/call-me-maybe/download/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= caller-callsite@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/caller-callsite/download/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= dependencies: callsites "^2.0.0" caller-path@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/caller-path/download/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= dependencies: caller-callsite "^2.0.0" callsites@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/callsites/download/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= callsites@^3.0.0: version "3.1.0" - resolved "https://registry.npm.taobao.org/callsites/download/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M= + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camel-case@3.0.x: version "3.0.0" - resolved "https://registry.npm.taobao.org/camel-case/download/camel-case-3.0.0.tgz?cache=0&sync_timestamp=1606867780255&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamel-case%2Fdownload%2Fcamel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= dependencies: no-case "^2.2.0" @@ -2407,43 +2435,43 @@ camel-case@3.0.x: camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.npm.taobao.org/camelcase/download/camelcase-5.3.1.tgz?cache=0&sync_timestamp=1603921779318&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA= + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== camelcase@^6.0.0: version "6.2.0" - resolved "https://registry.npm.taobao.org/camelcase/download/camelcase-6.2.0.tgz?cache=0&sync_timestamp=1603921779318&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha1-kkr4gcnVJaydh/QNlk5c6pgqGAk= + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== caniuse-api@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/caniuse-api/download/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha1-Xk2Q4idJYdRikZl99Znj7QCO5MA= + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== dependencies: browserslist "^4.0.0" caniuse-lite "^1.0.0" lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001173: - version "1.0.30001173" - resolved "https://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30001173.tgz?cache=0&sync_timestamp=1609737049958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcaniuse-lite%2Fdownload%2Fcaniuse-lite-1.0.30001173.tgz#3c47bbe3cd6d7a9eda7f50ac016d158005569f56" - integrity sha1-PEe7481tep7af1CsAW0VgAVWn1Y= +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001181: + version "1.0.30001202" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001202.tgz#4cb3bd5e8a808e8cd89e4e66c549989bc8137201" + integrity sha512-ZcijQNqrcF8JNLjzvEiXqX4JUYxoZa7Pvcsd9UD8Kz4TvhTonOSNRsK+qtvpVL4l6+T1Rh4LFtLfnNWg6BGWCQ== case-sensitive-paths-webpack-plugin@^2.3.0: - version "2.3.0" - resolved "https://registry.npm.taobao.org/case-sensitive-paths-webpack-plugin/download/case-sensitive-paths-webpack-plugin-2.3.0.tgz?cache=0&sync_timestamp=1598867172964&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcase-sensitive-paths-webpack-plugin%2Fdownload%2Fcase-sensitive-paths-webpack-plugin-2.3.0.tgz#23ac613cc9a856e4f88ff8bb73bbb5e989825cf7" - integrity sha1-I6xhPMmoVuT4j/i7c7u16YmCXPc= + version "2.4.0" + resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4" + integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw== caseless@~0.12.0: version "0.12.0" - resolved "https://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" - resolved "https://registry.npm.taobao.org/chalk/download/chalk-2.4.2.tgz?cache=0&sync_timestamp=1591687018980&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ= + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -2451,26 +2479,26 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4 chalk@^4.0.0, chalk@^4.1.0: version "4.1.0" - resolved "https://registry.npm.taobao.org/chalk/download/chalk-4.1.0.tgz?cache=0&sync_timestamp=1591687018980&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" - integrity sha1-ThSHCmGNni7dl92DRf2dncMVZGo= + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" chardet@^0.7.0: version "0.7.0" - resolved "https://registry.npm.taobao.org/chardet/download/chardet-0.7.0.tgz?cache=0&sync_timestamp=1601032487499&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchardet%2Fdownload%2Fchardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha1-kAlISfCTfy7twkJdDSip5fDLrZ4= + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== check-types@^8.0.3: version "8.0.3" - resolved "https://registry.npm.taobao.org/check-types/download/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" - integrity sha1-M1bMoZyIlUTy16le1JzlCKDs9VI= + resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" + integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ== chokidar@^2.1.8: version "2.1.8" - resolved "https://registry.npm.taobao.org/chokidar/download/chokidar-2.1.8.tgz?cache=0&sync_timestamp=1609920482468&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha1-gEs6e2qZNYw8XGHnHYco8EHP+Rc= + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== dependencies: anymatch "^2.0.0" async-each "^1.0.1" @@ -2487,9 +2515,9 @@ chokidar@^2.1.8: fsevents "^1.2.7" chokidar@^3.4.1: - version "3.5.0" - resolved "https://registry.npm.taobao.org/chokidar/download/chokidar-3.5.0.tgz?cache=0&sync_timestamp=1609920482468&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-3.5.0.tgz#458a4816a415e9d3b3caa4faec2b96a6935a9e65" - integrity sha1-RYpIFqQV6dOzyqT67CuWppNanmU= + version "3.5.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -2503,33 +2531,33 @@ chokidar@^3.4.1: chownr@^1.1.1, chownr@^1.1.2: version "1.1.4" - resolved "https://registry.npm.taobao.org/chownr/download/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha1-b8nXtC0ypYNZYzdmbn0ICE2izGs= + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== chrome-trace-event@^1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/chrome-trace-event/download/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" - integrity sha1-I0CQ7pfH1K0aLEvq4nUF3v/GCKQ= + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== dependencies: tslib "^1.9.0" ci-info@^1.5.0: version "1.6.0" - resolved "https://registry.npm.taobao.org/ci-info/download/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" - integrity sha1-LKINu5zrMtRSSmgzAzE/AwSx5Jc= + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" + integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" - resolved "https://registry.npm.taobao.org/cipher-base/download/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94= + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" class-utils@^0.3.5: version "0.3.6" - resolved "https://registry.npm.taobao.org/class-utils/download/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha1-+TNprouafOAv1B+q0MqDAzGQxGM= + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" define-property "^0.2.5" @@ -2538,56 +2566,56 @@ class-utils@^0.3.5: clean-css@4.2.x: version "4.2.3" - resolved "https://registry.npm.taobao.org/clean-css/download/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" - integrity sha1-UHtd59l7SO5T2ErbAWD/YhY4D3g= + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" + integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== dependencies: source-map "~0.6.0" clean-stack@^2.0.0: version "2.2.0" - resolved "https://registry.npm.taobao.org/clean-stack/download/clean-stack-2.2.0.tgz?cache=0&sync_timestamp=1605702384104&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fclean-stack%2Fdownload%2Fclean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha1-7oRy27Ep5yezHooQpCfe6d/kAIs= + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== cli-cursor@^2.1.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/cli-cursor/download/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= dependencies: restore-cursor "^2.0.0" cli-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.npm.taobao.org/cli-cursor/download/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha1-JkMFp65JDR0Dvwybp8kl0XU68wc= + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== dependencies: restore-cursor "^3.1.0" cli-highlight@^2.1.4: - version "2.1.9" - resolved "https://registry.npm.taobao.org/cli-highlight/download/cli-highlight-2.1.9.tgz#4f4ecb05326d70d56d4b4249fabf9a70fb002497" - integrity sha1-T07LBTJtcNVtS0JJ+r+acPsAJJc= + version "2.1.10" + resolved "https://registry.yarnpkg.com/cli-highlight/-/cli-highlight-2.1.10.tgz#26a087da9209dce4fcb8cf5427dc97cd96ac173a" + integrity sha512-CcPFD3JwdQ2oSzy+AMG6j3LRTkNjM82kzcSKzoVw6cLanDCJNlsLjeqVTOTfOfucnWv5F0rmBemVf1m9JiIasw== dependencies: chalk "^4.0.0" highlight.js "^10.0.0" mz "^2.4.0" parse5 "^5.1.1" parse5-htmlparser2-tree-adapter "^6.0.0" - yargs "^15.0.0" + yargs "^16.0.0" cli-spinners@^2.0.0: version "2.5.0" - resolved "https://registry.npm.taobao.org/cli-spinners/download/cli-spinners-2.5.0.tgz#12763e47251bf951cb75c201dfa58ff1bcb2d047" - integrity sha1-EnY+RyUb+VHLdcIB36WP8byy0Ec= + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.5.0.tgz#12763e47251bf951cb75c201dfa58ff1bcb2d047" + integrity sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ== cli-width@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/cli-width/download/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha1-ovSEN6LKqaIkNueUvwceyeYc7fY= + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== clipboardy@^2.3.0: version "2.3.0" - resolved "https://registry.npm.taobao.org/clipboardy/download/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290" - integrity sha1-PCkDZQxo5GqRs4iYW8J3QofbopA= + resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290" + integrity sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ== dependencies: arch "^2.1.1" execa "^1.0.0" @@ -2595,8 +2623,8 @@ clipboardy@^2.3.0: cliui@^5.0.0: version "5.0.0" - resolved "https://registry.npm.taobao.org/cliui/download/cliui-5.0.0.tgz?cache=0&sync_timestamp=1604880226973&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcliui%2Fdownload%2Fcliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha1-3u/P2y6AB4SqNPRvoI4GhRx7u8U= + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== dependencies: string-width "^3.1.0" strip-ansi "^5.2.0" @@ -2604,22 +2632,31 @@ cliui@^5.0.0: cliui@^6.0.0: version "6.0.0" - resolved "https://registry.npm.taobao.org/cliui/download/cliui-6.0.0.tgz?cache=0&sync_timestamp=1604880226973&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcliui%2Fdownload%2Fcliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" - integrity sha1-UR1wLAxOQcoVbX0OlgIfI+EyJbE= + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== dependencies: string-width "^4.2.0" strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + clone@^1.0.2: version "1.0.4" - resolved "https://registry.npm.taobao.org/clone/download/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= coa@^2.0.2: version "2.0.2" - resolved "https://registry.npm.taobao.org/coa/download/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" - integrity sha1-Q/bCEVG07yv1cYfbDXPeIp4+fsM= + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== dependencies: "@types/q" "^1.5.1" chalk "^2.4.1" @@ -2627,7 +2664,7 @@ coa@^2.0.2: collection-visit@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/collection-visit/download/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" @@ -2635,97 +2672,97 @@ collection-visit@^1.0.0: color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" - resolved "https://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg= + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM= + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@1.1.3: version "1.1.3" - resolved "https://registry.npm.taobao.org/color-name/download/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" - resolved "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha1-wqCah6y95pVD3m9j+jmVyCbFNqI= + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-string@^1.5.4: - version "1.5.4" - resolved "https://registry.npm.taobao.org/color-string/download/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6" - integrity sha1-3VHNJc/ulT0Tj+QAI3LMPQ5QTLY= + version "1.5.5" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.5.tgz#65474a8f0e7439625f3d27a6a19d89fc45223014" + integrity sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" color@^3.0.0: version "3.1.3" - resolved "https://registry.npm.taobao.org/color/download/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e" - integrity sha1-ymf7TnuX1hHc3jns7tQiBn2RWW4= + resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e" + integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ== dependencies: color-convert "^1.9.1" color-string "^1.5.4" -colorette@^1.2.1: - version "1.2.1" - resolved "https://registry.npm.taobao.org/colorette/download/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" - integrity sha1-TQuSEyXBT6+SYzCGpTbbbolWSxs= +colorette@^1.2.1, colorette@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" - resolved "https://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha1-w9RaizT9cwYxoRCoolIGgrMdWn8= + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" commander@2.17.x: version "2.17.1" - resolved "https://registry.npm.taobao.org/commander/download/commander-2.17.1.tgz?cache=0&sync_timestamp=1607931426196&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha1-vXerfebelCBc6sxy8XFtKfIKd78= + resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== commander@^2.18.0, commander@^2.20.0: version "2.20.3" - resolved "https://registry.npm.taobao.org/commander/download/commander-2.20.3.tgz?cache=0&sync_timestamp=1607931426196&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha1-/UhehMA+tIgcIHIrpIA16FMa6zM= + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== commander@~2.19.0: version "2.19.0" - resolved "https://registry.npm.taobao.org/commander/download/commander-2.19.0.tgz?cache=0&sync_timestamp=1607931426196&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha1-9hmKqE5bg8RgVLlN3tv+1e6f8So= + resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== common-tags@^1.8.0: version "1.8.0" - resolved "https://registry.npm.taobao.org/common-tags/download/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" - integrity sha1-jjFT5ULUo56bEFVENK+q+YlWqTc= + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" + integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw== commondir@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/commondir/download/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= component-emitter@^1.2.1: version "1.3.0" - resolved "https://registry.npm.taobao.org/component-emitter/download/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A= + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== compressible@~2.0.16: version "2.0.18" - resolved "https://registry.npm.taobao.org/compressible/download/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha1-r1PMprBw1MPAdQ+9dyhqbXzEb7o= + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== dependencies: mime-db ">= 1.43.0 < 2" compression@^1.7.4: version "1.7.4" - resolved "https://registry.npm.taobao.org/compression/download/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha1-lVI+/xcMpXwpoMpB5v4TH0Hlu48= + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== dependencies: accepts "~1.3.5" bytes "3.0.0" @@ -2737,13 +2774,13 @@ compression@^1.7.4: concat-map@0.0.1: version "0.0.1" - resolved "https://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concat-stream@^1.5.0: version "1.6.2" - resolved "https://registry.npm.taobao.org/concat-stream/download/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ= + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" inherits "^2.0.3" @@ -2752,71 +2789,71 @@ concat-stream@^1.5.0: connect-history-api-fallback@^1.6.0: version "1.6.0" - resolved "https://registry.npm.taobao.org/connect-history-api-fallback/download/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha1-izIIk1kwjRERFdgcrT/Oq4iPl7w= + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" + integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== consola@^2.15.0: - version "2.15.0" - resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.0.tgz#40fc4eefa4d2f8ef2e2806147f056ea207fcc0e9" - integrity sha512-vlcSGgdYS26mPf7qNi+dCisbhiyDnrN1zaRbw3CSuc2wGOMEGGPsp46PdRG5gqXwgtJfjxDkxRNAgRPr1B77vQ== + version "2.15.3" + resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550" + integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw== console-browserify@^1.1.0: version "1.2.0" - resolved "https://registry.npm.taobao.org/console-browserify/download/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha1-ZwY871fOts9Jk6KrOlWECujEkzY= + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== consolidate@^0.15.1: version "0.15.1" - resolved "https://registry.npm.taobao.org/consolidate/download/consolidate-0.15.1.tgz?cache=0&sync_timestamp=1599596658886&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fconsolidate%2Fdownload%2Fconsolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7" - integrity sha1-IasEMjXHGgfUXZqtmFk7DbpWurc= + resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7" + integrity sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw== dependencies: bluebird "^3.1.1" consolidate@^0.16.0: version "0.16.0" - resolved "https://registry.npm.taobao.org/consolidate/download/consolidate-0.16.0.tgz?cache=0&sync_timestamp=1599596658886&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fconsolidate%2Fdownload%2Fconsolidate-0.16.0.tgz#a11864768930f2f19431660a65906668f5fbdc16" - integrity sha1-oRhkdokw8vGUMWYKZZBmaPX73BY= + resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.16.0.tgz#a11864768930f2f19431660a65906668f5fbdc16" + integrity sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ== dependencies: bluebird "^3.7.2" constants-browserify@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/constants-browserify/download/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= content-disposition@0.5.3: version "0.5.3" - resolved "https://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70= + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== dependencies: safe-buffer "5.1.2" content-type@~1.0.4: version "1.0.4" - resolved "https://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha1-4TjMdeBAxyexlm/l5fjJruJW/js= + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.7.0: version "1.7.0" - resolved "https://registry.npm.taobao.org/convert-source-map/download/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha1-F6LLiC1/d9NJBYXizmxSRCSjpEI= + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== dependencies: safe-buffer "~5.1.1" cookie-signature@1.0.6: version "1.0.6" - resolved "https://registry.npm.taobao.org/cookie-signature/download/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= cookie@0.4.0: version "0.4.0" - resolved "https://registry.npm.taobao.org/cookie/download/cookie-0.4.0.tgz?cache=0&sync_timestamp=1587525998658&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcookie%2Fdownload%2Fcookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha1-vrQ35wIrO21JAZ0IhmUwPr6cFLo= + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== copy-concurrently@^1.0.0: version "1.0.5" - resolved "https://registry.npm.taobao.org/copy-concurrently/download/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" - integrity sha1-kilzmMrjSTf8r9bsgTnBgFHwteA= + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== dependencies: aproba "^1.1.1" fs-write-stream-atomic "^1.0.8" @@ -2827,13 +2864,13 @@ copy-concurrently@^1.0.0: copy-descriptor@^0.1.0: version "0.1.1" - resolved "https://registry.npm.taobao.org/copy-descriptor/download/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= copy-webpack-plugin@^5.1.1: version "5.1.2" - resolved "https://registry.npm.taobao.org/copy-webpack-plugin/download/copy-webpack-plugin-5.1.2.tgz#8a889e1dcafa6c91c6cd4be1ad158f1d3823bae2" - integrity sha1-ioieHcr6bJHGzUvhrRWPHTgjuuI= + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz#8a889e1dcafa6c91c6cd4be1ad158f1d3823bae2" + integrity sha512-Uh7crJAco3AjBvgAy9Z75CjK8IG+gxaErro71THQ+vv/bl4HaQcpkexAY8KVW/T6D2W2IRr+couF/knIRkZMIQ== dependencies: cacache "^12.0.3" find-cache-dir "^2.1.0" @@ -2848,33 +2885,33 @@ copy-webpack-plugin@^5.1.1: serialize-javascript "^4.0.0" webpack-log "^2.0.0" -core-js-compat@^3.6.5, core-js-compat@^3.8.0: - version "3.8.2" - resolved "https://registry.npm.taobao.org/core-js-compat/download/core-js-compat-3.8.2.tgz?cache=0&sync_timestamp=1609682093526&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js-compat%2Fdownload%2Fcore-js-compat-3.8.2.tgz#3717f51f6c3d2ebba8cbf27619b57160029d1d4c" - integrity sha1-Nxf1H2w9Lruoy/J2GbVxYAKdHUw= +core-js-compat@^3.6.5, core-js-compat@^3.8.1, core-js-compat@^3.9.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.9.1.tgz#4e572acfe90aff69d76d8c37759d21a5c59bb455" + integrity sha512-jXAirMQxrkbiiLsCx9bQPJFA6llDadKMpYrBJQJ3/c4/vsPP/fAf29h24tviRlvwUL6AmY5CHLu2GvjuYviQqA== dependencies: - browserslist "^4.16.0" + browserslist "^4.16.3" semver "7.0.0" core-js@^2.4.0: version "2.6.12" - resolved "https://registry.npm.taobao.org/core-js/download/core-js-2.6.12.tgz?cache=0&sync_timestamp=1609682093261&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" - integrity sha1-2TM9+nsGXjR8xWgiGdb2kIWcwuw= + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== core-js@^3.6.5: - version "3.8.2" - resolved "https://registry.npm.taobao.org/core-js/download/core-js-3.8.2.tgz?cache=0&sync_timestamp=1609682093261&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-3.8.2.tgz#0a1fd6709246da9ca8eff5bb0cbd15fba9ac7044" - integrity sha1-Ch/WcJJG2pyo7/W7DL0V+6mscEQ= + version "3.9.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.9.1.tgz#cec8de593db8eb2a85ffb0dbdeb312cb6e5460ae" + integrity sha512-gSjRvzkxQc1zjM/5paAmL4idJBFzuJoo+jDjF1tStYFMV2ERfD02HhahhCGXUyHxQRG4yFKVSdO6g62eoRMcDg== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" - resolved "https://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= cosmiconfig@^5.0.0: version "5.2.1" - resolved "https://registry.npm.taobao.org/cosmiconfig/download/cosmiconfig-5.2.1.tgz?cache=0&sync_timestamp=1596310641928&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcosmiconfig%2Fdownload%2Fcosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha1-BA9yaAnFked6F8CjYmykW08Wixo= + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== dependencies: import-fresh "^2.0.0" is-directory "^0.3.1" @@ -2883,16 +2920,16 @@ cosmiconfig@^5.0.0: create-ecdh@^4.0.0: version "4.0.4" - resolved "https://registry.npm.taobao.org/create-ecdh/download/create-ecdh-4.0.4.tgz?cache=0&sync_timestamp=1596557469480&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcreate-ecdh%2Fdownload%2Fcreate-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha1-1uf0v/pmc2CFoHYv06YyaE2rzE4= + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== dependencies: bn.js "^4.1.0" elliptic "^6.5.3" create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" - resolved "https://registry.npm.taobao.org/create-hash/download/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY= + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" inherits "^2.0.1" @@ -2902,8 +2939,8 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" - resolved "https://registry.npm.taobao.org/create-hmac/download/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8= + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" create-hash "^1.1.0" @@ -2914,7 +2951,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: cross-spawn@^5.0.1: version "5.1.0" - resolved "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-5.1.0.tgz?cache=0&sync_timestamp=1598867150563&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcross-spawn%2Fdownload%2Fcross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= dependencies: lru-cache "^4.0.1" @@ -2923,8 +2960,8 @@ cross-spawn@^5.0.1: cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" - resolved "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-6.0.5.tgz?cache=0&sync_timestamp=1598867150563&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcross-spawn%2Fdownload%2Fcross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q= + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== dependencies: nice-try "^1.0.4" path-key "^2.0.1" @@ -2934,8 +2971,8 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: cross-spawn@^7.0.0: version "7.0.3" - resolved "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-7.0.3.tgz?cache=0&sync_timestamp=1598867150563&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcross-spawn%2Fdownload%2Fcross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha1-9zqFudXUHQRVUcF34ogtSshXKKY= + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" @@ -2943,8 +2980,8 @@ cross-spawn@^7.0.0: crypto-browserify@^3.11.0: version "3.12.0" - resolved "https://registry.npm.taobao.org/crypto-browserify/download/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha1-OWz58xN/A+S45TLFj2mCVOAPgOw= + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" browserify-sign "^4.0.0" @@ -2965,21 +3002,21 @@ crypto-random-string@^1.0.0: css-color-names@0.0.4, css-color-names@^0.0.4: version "0.0.4" - resolved "https://registry.npm.taobao.org/css-color-names/download/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= css-declaration-sorter@^4.0.1: version "4.0.1" - resolved "https://registry.npm.taobao.org/css-declaration-sorter/download/css-declaration-sorter-4.0.1.tgz?cache=0&sync_timestamp=1604519240728&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcss-declaration-sorter%2Fdownload%2Fcss-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" - integrity sha1-wZiUD2OnbX42wecQGLABchBUyyI= + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" + integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== dependencies: postcss "^7.0.1" timsort "^0.3.0" css-loader@^3.5.3: version "3.6.0" - resolved "https://registry.npm.taobao.org/css-loader/download/css-loader-3.6.0.tgz?cache=0&sync_timestamp=1604507228266&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcss-loader%2Fdownload%2Fcss-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" - integrity sha1-Lkssfm4tJ/jI8o9hv/zS5ske9kU= + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" + integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== dependencies: camelcase "^5.3.1" cssesc "^3.0.0" @@ -2997,13 +3034,13 @@ css-loader@^3.5.3: css-select-base-adapter@^0.1.1: version "0.1.1" - resolved "https://registry.npm.taobao.org/css-select-base-adapter/download/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha1-Oy/0lyzDYquIVhUHqVQIoUMhNdc= + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== css-select@^2.0.0, css-select@^2.0.2: version "2.1.0" - resolved "https://registry.npm.taobao.org/css-select/download/css-select-2.1.0.tgz?cache=0&sync_timestamp=1608486062507&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcss-select%2Fdownload%2Fcss-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" - integrity sha1-ajRlM1ZjWTSoG6ymjQJVQyEF2+8= + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" + integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== dependencies: boolbase "^1.0.0" css-what "^3.2.1" @@ -3012,34 +3049,34 @@ css-select@^2.0.0, css-select@^2.0.2: css-tree@1.0.0-alpha.37: version "1.0.0-alpha.37" - resolved "https://registry.npm.taobao.org/css-tree/download/css-tree-1.0.0-alpha.37.tgz?cache=0&sync_timestamp=1606404079672&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcss-tree%2Fdownload%2Fcss-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" - integrity sha1-mL69YsTB2flg7DQM+fdSLjBwmiI= + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" + integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== dependencies: mdn-data "2.0.4" source-map "^0.6.1" css-tree@^1.1.2: version "1.1.2" - resolved "https://registry.npm.taobao.org/css-tree/download/css-tree-1.1.2.tgz?cache=0&sync_timestamp=1606404079672&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcss-tree%2Fdownload%2Fcss-tree-1.1.2.tgz#9ae393b5dafd7dae8a622475caec78d3d8fbd7b5" - integrity sha1-muOTtdr9fa6KYiR1yux409j717U= + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.2.tgz#9ae393b5dafd7dae8a622475caec78d3d8fbd7b5" + integrity sha512-wCoWush5Aeo48GLhfHPbmvZs59Z+M7k5+B1xDnXbdWNcEF423DoFdqSWE0PM5aNk5nI5cp1q7ms36zGApY/sKQ== dependencies: mdn-data "2.0.14" source-map "^0.6.1" css-what@^3.2.1: version "3.4.2" - resolved "https://registry.npm.taobao.org/css-what/download/css-what-3.4.2.tgz?cache=0&sync_timestamp=1602570920759&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcss-what%2Fdownload%2Fcss-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" - integrity sha1-6nAm/LAXd+295SEk4h8yfnrpUOQ= + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" + integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== cssesc@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/cssesc/download/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha1-N3QZGZA7hoVl4cCep0dEXNGJg+4= + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== cssnano-preset-default@^4.0.0, cssnano-preset-default@^4.0.7: version "4.0.7" - resolved "https://registry.npm.taobao.org/cssnano-preset-default/download/cssnano-preset-default-4.0.7.tgz?cache=0&sync_timestamp=1603212673818&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcssnano-preset-default%2Fdownload%2Fcssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" - integrity sha1-UexmLM/KD4izltzZZ5zbkxvhf3Y= + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" + integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== dependencies: css-declaration-sorter "^4.0.1" cssnano-util-raw-cache "^4.0.1" @@ -3074,30 +3111,30 @@ cssnano-preset-default@^4.0.0, cssnano-preset-default@^4.0.7: cssnano-util-get-arguments@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/cssnano-util-get-arguments/download/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" + resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= cssnano-util-get-match@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/cssnano-util-get-match/download/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" + resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= cssnano-util-raw-cache@^4.0.1: version "4.0.1" - resolved "https://registry.npm.taobao.org/cssnano-util-raw-cache/download/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" - integrity sha1-sm1f1fcqEd/np4RvtMZyYPlr8oI= + resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" + integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== dependencies: postcss "^7.0.0" cssnano-util-same-parent@^4.0.0: version "4.0.1" - resolved "https://registry.npm.taobao.org/cssnano-util-same-parent/download/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" - integrity sha1-V0CC+yhZ0ttDOFWDXZqEVuoYu/M= + resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" + integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== cssnano@^4.0.0, cssnano@^4.1.10: version "4.1.10" - resolved "https://registry.npm.taobao.org/cssnano/download/cssnano-4.1.10.tgz?cache=0&sync_timestamp=1603214495214&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcssnano%2Fdownload%2Fcssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" - integrity sha1-CsQfCxPRPUZUh+ERt3jULaYxuLI= + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" + integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== dependencies: cosmiconfig "^5.0.0" cssnano-preset-default "^4.0.7" @@ -3106,19 +3143,19 @@ cssnano@^4.0.0, cssnano@^4.1.10: csso@^4.0.2: version "4.2.0" - resolved "https://registry.npm.taobao.org/csso/download/csso-4.2.0.tgz?cache=0&sync_timestamp=1606408883298&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcsso%2Fdownload%2Fcsso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha1-6jpWE0bo3J9UbW/r7dUBh884lSk= + resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" + integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== dependencies: css-tree "^1.1.2" cyclist@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/cyclist/download/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= dashdash@^1.12.0: version "1.14.1" - resolved "https://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz?cache=0&sync_timestamp=1601073407658&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdashdash%2Fdownload%2Fdashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= dependencies: assert-plus "^1.0.0" @@ -3130,39 +3167,39 @@ de-indent@^1.0.2: debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" - resolved "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1607566782124&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8= + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" debug@^3.1.1, debug@^3.2.6: version "3.2.7" - resolved "https://registry.npm.taobao.org/debug/download/debug-3.2.7.tgz?cache=0&sync_timestamp=1607566782124&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha1-clgLfpFF+zm2Z2+cXl+xALk0F5o= + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.3.1" - resolved "https://registry.npm.taobao.org/debug/download/debug-4.3.1.tgz?cache=0&sync_timestamp=1607566782124&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" - integrity sha1-8NIpxQXgxtjEmsVT0bE9wYP2su4= + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: ms "2.1.2" decamelize@^1.2.0: version "1.2.0" - resolved "https://registry.npm.taobao.org/decamelize/download/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decode-uri-component@^0.2.0: version "0.2.0" - resolved "https://registry.npm.taobao.org/decode-uri-component/download/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= deep-equal@^1.0.1: version "1.1.1" - resolved "https://registry.npm.taobao.org/deep-equal/download/deep-equal-1.1.1.tgz?cache=0&sync_timestamp=1606859714626&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdeep-equal%2Fdownload%2Fdeep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha1-tcmMlCzv+vfLBR4k4UNKJaLmB2o= + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== dependencies: is-arguments "^1.0.4" is-date-object "^1.0.1" @@ -3178,69 +3215,69 @@ deep-extend@^0.6.0: deep-is@~0.1.3: version "0.1.3" - resolved "https://registry.npm.taobao.org/deep-is/download/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= deepmerge@^1.5.2: version "1.5.2" - resolved "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz?cache=0&sync_timestamp=1593091003052&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdeepmerge%2Fdownload%2Fdeepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753" - integrity sha1-EEmdhohEza1P7ghC34x/bwyVp1M= + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753" + integrity sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ== default-gateway@^4.2.0: version "4.2.0" - resolved "https://registry.npm.taobao.org/default-gateway/download/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" - integrity sha1-FnEEx1AMIRX23WmwpTa7jtcgVSs= + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" + integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== dependencies: execa "^1.0.0" ip-regex "^2.1.0" default-gateway@^5.0.5: version "5.0.5" - resolved "https://registry.npm.taobao.org/default-gateway/download/default-gateway-5.0.5.tgz#4fd6bd5d2855d39b34cc5a59505486e9aafc9b10" - integrity sha1-T9a9XShV05s0zFpZUFSG6ar8mxA= + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-5.0.5.tgz#4fd6bd5d2855d39b34cc5a59505486e9aafc9b10" + integrity sha512-z2RnruVmj8hVMmAnEJMTIJNijhKCDiGjbLP+BHJFOT7ld3Bo5qcIBpVYDniqhbMIIf+jZDlkP2MkPXiQy/DBLA== dependencies: execa "^3.3.0" defaults@^1.0.3: version "1.0.3" - resolved "https://registry.npm.taobao.org/defaults/download/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= dependencies: clone "^1.0.2" define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" - resolved "https://registry.npm.taobao.org/define-properties/download/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE= + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" - resolved "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" - resolved "https://registry.npm.taobao.org/define-property/download/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha1-1Flono1lS6d+AqgX+HENcCyxbp0= + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" del@^4.1.1: version "4.1.1" - resolved "https://registry.npm.taobao.org/del/download/del-4.1.1.tgz?cache=0&sync_timestamp=1601076915294&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdel%2Fdownload%2Fdel-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" - integrity sha1-no8RciLqRKMf86FWwEm5kFKp8LQ= + resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" + integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== dependencies: "@types/glob" "^7.1.1" globby "^6.1.0" @@ -3252,36 +3289,36 @@ del@^4.1.1: delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= depd@~1.1.2: version "1.1.2" - resolved "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= des.js@^1.0.0: version "1.0.1" - resolved "https://registry.npm.taobao.org/des.js/download/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha1-U4IULhvcU/hdhtU+X0qn3rkeCEM= + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" destroy@~1.0.4: version "1.0.4" - resolved "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= detect-node@^2.0.4: - version "2.0.4" - resolved "https://registry.npm.taobao.org/detect-node/download/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" - integrity sha1-AU7o+PZpxcWAI9pkuBecCDooxGw= + version "2.0.5" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.5.tgz#9d270aa7eaa5af0b72c4c9d9b814e7f4ce738b79" + integrity sha512-qi86tE6hRcFHy8jI1m2VG+LaPUR1LhqDa5G8tVjuUXmOrpuAgqsA1pN0+ldgr3aKUH+QLI9hCY/OcRYisERejw== diffie-hellman@^5.0.0: version "5.0.3" - resolved "https://registry.npm.taobao.org/diffie-hellman/download/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha1-QOjumPVaIUlgcUaSHGPhrl89KHU= + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" @@ -3289,109 +3326,109 @@ diffie-hellman@^5.0.0: dir-glob@^2.0.0, dir-glob@^2.2.2: version "2.2.2" - resolved "https://registry.npm.taobao.org/dir-glob/download/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" - integrity sha1-+gnwaUFTyJGLGLoN6vrpR2n8UMQ= + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" + integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== dependencies: path-type "^3.0.0" dns-equal@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/dns-equal/download/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= dns-packet@^1.3.1: version "1.3.1" - resolved "https://registry.npm.taobao.org/dns-packet/download/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" - integrity sha1-EqpCaYEHW+UAuRDu3NC0fdfe2lo= + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" + integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg== dependencies: ip "^1.1.0" safe-buffer "^5.0.1" dns-txt@^2.0.2: version "2.0.2" - resolved "https://registry.npm.taobao.org/dns-txt/download/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" + resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= dependencies: buffer-indexof "^1.0.0" doctrine@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/doctrine/download/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha1-rd6+rXKmV023g2OdyHoSF3OXOWE= + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" dom-converter@^0.2: version "0.2.0" - resolved "https://registry.npm.taobao.org/dom-converter/download/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" - integrity sha1-ZyGp2u4uKTaClVtq/kFncWJ7t2g= + resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" + integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== dependencies: utila "~0.4" dom-serializer@0: version "0.2.2" - resolved "https://registry.npm.taobao.org/dom-serializer/download/dom-serializer-0.2.2.tgz?cache=0&sync_timestamp=1607192967807&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdom-serializer%2Fdownload%2Fdom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha1-GvuB9TNxcXXUeGVd68XjMtn5u1E= + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== dependencies: domelementtype "^2.0.1" entities "^2.0.0" domain-browser@^1.1.1: version "1.2.0" - resolved "https://registry.npm.taobao.org/domain-browser/download/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto= + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== domelementtype@1, domelementtype@^1.3.1: version "1.3.1" - resolved "https://registry.npm.taobao.org/domelementtype/download/domelementtype-1.3.1.tgz?cache=0&sync_timestamp=1606866110836&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomelementtype%2Fdownload%2Fdomelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha1-0EjESzew0Qp/Kj1f7j9DM9eQSB8= + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== domelementtype@^2.0.1: version "2.1.0" - resolved "https://registry.npm.taobao.org/domelementtype/download/domelementtype-2.1.0.tgz?cache=0&sync_timestamp=1606866110836&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomelementtype%2Fdownload%2Fdomelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e" - integrity sha1-qFHAgKbRw9lDRK7RUdmfZp7fWF4= + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e" + integrity sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w== domhandler@^2.3.0: version "2.4.2" - resolved "https://registry.npm.taobao.org/domhandler/download/domhandler-2.4.2.tgz?cache=0&sync_timestamp=1606872524192&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomhandler%2Fdownload%2Fdomhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha1-iAUJfpM9ZehVRvcm1g9euItE+AM= + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== dependencies: domelementtype "1" domutils@^1.5.1, domutils@^1.7.0: version "1.7.0" - resolved "https://registry.npm.taobao.org/domutils/download/domutils-1.7.0.tgz?cache=0&sync_timestamp=1607393197963&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomutils%2Fdownload%2Fdomutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha1-Vuo0HoNOBuZ0ivehyyXaZ+qfjCo= + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== dependencies: dom-serializer "0" domelementtype "1" dot-prop@^5.2.0: version "5.3.0" - resolved "https://registry.npm.taobao.org/dot-prop/download/dot-prop-5.3.0.tgz?cache=0&sync_timestamp=1605778162251&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdot-prop%2Fdownload%2Fdot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" - integrity sha1-kMzOcIzZzYLMTcjD3dmr3VWyDog= + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== dependencies: is-obj "^2.0.0" dotenv-expand@^5.1.0: version "5.1.0" - resolved "https://registry.npm.taobao.org/dotenv-expand/download/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" - integrity sha1-P7rwIL/XlIhAcuomsel5HUWmKfA= + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" + integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== dotenv@^8.2.0: version "8.2.0" - resolved "https://registry.npm.taobao.org/dotenv/download/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" - integrity sha1-l+YZJZradQ7qPk6j4mvO6lQksWo= + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" + integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== duplexer@^0.1.1: version "0.1.2" - resolved "https://registry.npm.taobao.org/duplexer/download/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha1-Or5DrvODX4rgd9E23c4PJ2sEAOY= + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" - resolved "https://registry.npm.taobao.org/duplexify/download/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha1-Kk31MX9sz9kfhtb9JdjYoQO4gwk= + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== dependencies: end-of-stream "^1.0.0" inherits "^2.0.1" @@ -3400,12 +3437,12 @@ duplexify@^3.4.2, duplexify@^3.6.0: easy-stack@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/easy-stack/download/easy-stack-1.0.1.tgz?cache=0&sync_timestamp=1605128933665&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feasy-stack%2Fdownload%2Feasy-stack-1.0.1.tgz#8afe4264626988cabb11f3c704ccd0c835411066" - integrity sha1-iv5CZGJpiMq7EfPHBMzQyDVBEGY= + resolved "https://registry.yarnpkg.com/easy-stack/-/easy-stack-1.0.1.tgz#8afe4264626988cabb11f3c704ccd0c835411066" + integrity sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w== ecc-jsbn@~0.1.1: version "0.1.2" - resolved "https://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= dependencies: jsbn "~0.1.0" @@ -3413,68 +3450,68 @@ ecc-jsbn@~0.1.1: ee-first@1.1.1: version "1.1.1" - resolved "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= ejs@^2.6.1: version "2.7.4" - resolved "https://registry.npm.taobao.org/ejs/download/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" - integrity sha1-SGYSh1c9zFPjZsehrlLDoSDuybo= + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" + integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.3.634: - version "1.3.634" - resolved "https://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.634.tgz?cache=0&sync_timestamp=1609814110907&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felectron-to-chromium%2Fdownload%2Felectron-to-chromium-1.3.634.tgz#82ea400f520f739c4f6ff00c1f7524827a917d25" - integrity sha1-gupAD1IPc5xPb/AMH3UkgnqRfSU= +electron-to-chromium@^1.3.649: + version "1.3.691" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.691.tgz#a671eaf135a3ccec0915eb8d844a0952aba79f3b" + integrity sha512-ZqiO69KImmOGCyoH0icQPU3SndJiW93juEvf63gQngyhODO6SpQIPMTOHldtCs5DS5GMKvAkquk230E2zt2vpw== elliptic@^6.5.3: - version "6.5.3" - resolved "https://registry.npm.taobao.org/elliptic/download/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" - integrity sha1-y1nrLv2vc6C9eMzXAVpirW4Pk9Y= + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" + bn.js "^4.11.9" + brorand "^1.1.0" hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" emoji-regex@^7.0.1: version "7.0.3" - resolved "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-7.0.3.tgz?cache=0&sync_timestamp=1603212200036&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Femoji-regex%2Fdownload%2Femoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY= + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-8.0.0.tgz?cache=0&sync_timestamp=1603212200036&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Femoji-regex%2Fdownload%2Femoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha1-6Bj9ac5cz8tARZT4QpY79TFkzDc= + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== emojis-list@^2.0.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/emojis-list/download/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= emojis-list@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/emojis-list/download/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha1-VXBmIEatKeLpFucariYKvf9Pang= + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== encodeurl@~1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.4" - resolved "https://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha1-WuZKX0UFe682JuwU2gyl5LJDHrA= + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" -enhanced-resolve@^4.3.0: - version "4.3.0" - resolved "https://registry.npm.taobao.org/enhanced-resolve/download/enhanced-resolve-4.3.0.tgz?cache=0&sync_timestamp=1608557432903&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fenhanced-resolve%2Fdownload%2Fenhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" - integrity sha1-O4BvO/r8HsfeaVUe+TzKRsFwQSY= +enhanced-resolve@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" + integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== dependencies: graceful-fs "^4.1.2" memory-fs "^0.5.0" @@ -3482,74 +3519,61 @@ enhanced-resolve@^4.3.0: entities@^1.1.1: version "1.1.2" - resolved "https://registry.npm.taobao.org/entities/download/entities-1.1.2.tgz?cache=0&sync_timestamp=1602897347667&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fentities%2Fdownload%2Fentities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha1-vfpzUplmTfr9NFKe1PhSKidf6lY= + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== entities@^2.0.0: - version "2.1.0" - resolved "https://registry.npm.taobao.org/entities/download/entities-2.1.0.tgz?cache=0&sync_timestamp=1602897347667&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fentities%2Fdownload%2Fentities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" - integrity sha1-mS0xKc999ocLlsV4WMJJoSD4uLU= + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== errno@^0.1.3, errno@~0.1.7: version "0.1.8" - resolved "https://registry.npm.taobao.org/errno/download/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" - integrity sha1-i7Ppx9Rjvkl2/4iPdrSAnrwugR8= + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== dependencies: prr "~1.0.1" error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.npm.taobao.org/error-ex/download/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha1-tKxAZIEH/c3PriQvQovqihTU8b8= + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" error-stack-parser@^2.0.2: version "2.0.6" - resolved "https://registry.npm.taobao.org/error-stack-parser/download/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8" - integrity sha1-WpmnB716TFinl5AtSNgoA+3mqtg= + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8" + integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ== dependencies: stackframe "^1.1.1" -es-abstract@^1.17.0-next.1, es-abstract@^1.17.2: - version "1.17.7" - resolved "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.7.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" - integrity sha1-pN5hsvZpifx0IWdsHLl4dXOs5Uw= +es-abstract@^1.17.2, es-abstract@^1.18.0-next.2: + version "1.18.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0.tgz#ab80b359eecb7ede4c298000390bc5ac3ec7b5a4" + integrity sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw== dependencies: + call-bind "^1.0.2" es-to-primitive "^1.2.1" function-bind "^1.1.1" + get-intrinsic "^1.1.1" has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.2" - is-regex "^1.1.1" - object-inspect "^1.8.0" + has-symbols "^1.0.2" + is-callable "^1.2.3" + is-negative-zero "^2.0.1" + is-regex "^1.1.2" + is-string "^1.0.5" + object-inspect "^1.9.0" object-keys "^1.1.1" - object.assign "^4.1.1" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" - -es-abstract@^1.18.0-next.1: - version "1.18.0-next.1" - resolved "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.18.0-next.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" - integrity sha1-bjoKS9pxflAjqzuOkL7DYQjSLGg= - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.2" - is-negative-zero "^2.0.0" - is-regex "^1.1.1" - object-inspect "^1.8.0" - object-keys "^1.1.1" - object.assign "^4.1.1" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.0" es-to-primitive@^1.2.1: version "1.2.1" - resolved "https://registry.npm.taobao.org/es-to-primitive/download/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha1-5VzUyc3BiLzvsDs2bHNjI/xciYo= + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" @@ -3557,23 +3581,23 @@ es-to-primitive@^1.2.1: escalade@^3.1.1: version "3.1.1" - resolved "https://registry.npm.taobao.org/escalade/download/escalade-3.1.1.tgz?cache=0&sync_timestamp=1602567437752&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fescalade%2Fdownload%2Fescalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha1-2M/ccACWXFoBdLSoLqpcBVJ0LkA= + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-html@~1.0.3: version "1.0.3" - resolved "https://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= eslint-loader@^2.2.1: version "2.2.1" - resolved "https://registry.npm.taobao.org/eslint-loader/download/eslint-loader-2.2.1.tgz#28b9c12da54057af0845e2a6112701a2f6bf8337" - integrity sha1-KLnBLaVAV68IReKmEScBova/gzc= + resolved "https://registry.yarnpkg.com/eslint-loader/-/eslint-loader-2.2.1.tgz#28b9c12da54057af0845e2a6112701a2f6bf8337" + integrity sha512-RLgV9hoCVsMLvOxCuNjdqOrUqIj9oJg8hF44vzJaYqsAHuY9G2YAeN3joQ9nxP0p5Th9iFSIpKo+SD8KISxXRg== dependencies: loader-fs-cache "^1.0.0" loader-utils "^1.0.2" @@ -3582,54 +3606,54 @@ eslint-loader@^2.2.1: rimraf "^2.6.1" eslint-plugin-vue@^7.0.0-0: - version "7.4.1" - resolved "https://registry.npm.taobao.org/eslint-plugin-vue/download/eslint-plugin-vue-7.4.1.tgz?cache=0&sync_timestamp=1609808759758&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-vue%2Fdownload%2Feslint-plugin-vue-7.4.1.tgz#2526ef0c010c218824a89423dbe6ddbe76f04fd6" - integrity sha1-JSbvDAEMIYgkqJQj2+bdvnbwT9Y= + version "7.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-7.7.0.tgz#a90df4595e670821bf243bd2750ededdb74948b8" + integrity sha512-mYz4bpLGv5jx6YG/GvKkqbGSfV7uma2u1P3mLA41Q5vQl8W1MeuTneB8tfsLq6xxxesFubcrOC0BZBJ5R+eaCQ== dependencies: eslint-utils "^2.1.0" natural-compare "^1.4.0" semver "^7.3.2" - vue-eslint-parser "^7.3.0" + vue-eslint-parser "^7.6.0" eslint-scope@^4.0.3: version "4.0.3" - resolved "https://registry.npm.taobao.org/eslint-scope/download/eslint-scope-4.0.3.tgz?cache=0&sync_timestamp=1599933670126&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-scope%2Fdownload%2Feslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha1-ygODMxD2iJoyZHgaqC5j65z+eEg= + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" eslint-scope@^5.0.0: version "5.1.1" - resolved "https://registry.npm.taobao.org/eslint-scope/download/eslint-scope-5.1.1.tgz?cache=0&sync_timestamp=1599933670126&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-scope%2Fdownload%2Feslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha1-54blmmbLkrP2wfsNUIqrF0hI9Iw= + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: esrecurse "^4.3.0" estraverse "^4.1.1" eslint-utils@^1.4.3: version "1.4.3" - resolved "https://registry.npm.taobao.org/eslint-utils/download/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha1-dP7HxU0Hdrb2fgJRBAtYBlZOmB8= + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== dependencies: eslint-visitor-keys "^1.1.0" eslint-utils@^2.1.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/eslint-utils/download/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" - integrity sha1-0t5eA0JOcH3BDHQGjd7a5wh0Gyc= + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.3.0" - resolved "https://registry.npm.taobao.org/eslint-visitor-keys/download/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha1-MOvR73wv3/AcOk8VEESvJfqwUj4= + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== eslint@^6.7.2: version "6.8.0" - resolved "https://registry.npm.taobao.org/eslint/download/eslint-6.8.0.tgz?cache=0&sync_timestamp=1609553067553&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint%2Fdownload%2Feslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha1-YiYtZylzn5J1cjgkMC+yJ8jJP/s= + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" + integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -3671,8 +3695,8 @@ eslint@^6.7.2: espree@^6.1.2, espree@^6.2.1: version "6.2.1" - resolved "https://registry.npm.taobao.org/espree/download/espree-6.2.1.tgz?cache=0&sync_timestamp=1607146443455&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fespree%2Fdownload%2Fespree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" - integrity sha1-d/xy4f10SiBSwg84pbV1gy6Cc0o= + resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" + integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== dependencies: acorn "^7.1.1" acorn-jsx "^5.2.0" @@ -3680,32 +3704,32 @@ espree@^6.1.2, espree@^6.2.1: esprima@^4.0.0: version "4.0.1" - resolved "https://registry.npm.taobao.org/esprima/download/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha1-E7BM2z5sXRnfkatph6hpVhmwqnE= + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: - version "1.3.1" - resolved "https://registry.npm.taobao.org/esquery/download/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" - integrity sha1-t4tYKKqOIU4p+3TE1bdS4cAz2lc= +esquery@^1.0.1, esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== dependencies: estraverse "^5.1.0" esrecurse@^4.1.0, esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.npm.taobao.org/esrecurse/download/esrecurse-4.3.0.tgz?cache=0&sync_timestamp=1598898247102&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fesrecurse%2Fdownload%2Fesrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha1-eteWTWeauyi+5yzsY3WLHF0smSE= + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^4.1.1: version "4.3.0" - resolved "https://registry.npm.taobao.org/estraverse/download/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0= + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.1.0, estraverse@^5.2.0: version "5.2.0" - resolved "https://registry.npm.taobao.org/estraverse/download/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha1-MH30JUfmzHMk088DwVXVzbjFOIA= + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== estree-walker@^0.6.1: version "0.6.1" @@ -3719,52 +3743,52 @@ estree-walker@^1.0.1: estree-walker@^2.0.1: version "2.0.2" - resolved "https://registry.npm.taobao.org/estree-walker/download/estree-walker-2.0.2.tgz?cache=0&sync_timestamp=1607445746377&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Festree-walker%2Fdownload%2Festree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha1-UvAQF4wqTBF6d1fP6UKtt9LaTKw= + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.npm.taobao.org/esutils/download/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q= + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== etag@~1.8.1: version "1.8.1" - resolved "https://registry.npm.taobao.org/etag/download/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= event-pubsub@4.3.0: version "4.3.0" - resolved "https://registry.npm.taobao.org/event-pubsub/download/event-pubsub-4.3.0.tgz?cache=0&sync_timestamp=1606361626381&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fevent-pubsub%2Fdownload%2Fevent-pubsub-4.3.0.tgz#f68d816bc29f1ec02c539dc58c8dd40ce72cb36e" - integrity sha1-9o2Ba8KfHsAsU53FjI3UDOcss24= + resolved "https://registry.yarnpkg.com/event-pubsub/-/event-pubsub-4.3.0.tgz#f68d816bc29f1ec02c539dc58c8dd40ce72cb36e" + integrity sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ== eventemitter3@^4.0.0: version "4.0.7" - resolved "https://registry.npm.taobao.org/eventemitter3/download/eventemitter3-4.0.7.tgz?cache=0&sync_timestamp=1598517732045&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feventemitter3%2Fdownload%2Feventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha1-Lem2j2Uo1WRO9cWVJqG0oHMGFp8= + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== events@^3.0.0: - version "3.2.0" - resolved "https://registry.npm.taobao.org/events/download/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" - integrity sha1-k7h8GPjvzUICpGGuxN/AVWtjk3k= + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== eventsource@^1.0.7: - version "1.0.7" - resolved "https://registry.npm.taobao.org/eventsource/download/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0" - integrity sha1-j7xyyT/NNAiAkLwKTmT0tc7m2NA= + version "1.1.0" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.0.tgz#00e8ca7c92109e94b0ddf32dac677d841028cfaf" + integrity sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg== dependencies: original "^1.0.0" evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" - resolved "https://registry.npm.taobao.org/evp_bytestokey/download/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI= + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" safe-buffer "^5.1.1" execa@^0.8.0: version "0.8.0" - resolved "https://registry.npm.taobao.org/execa/download/execa-0.8.0.tgz?cache=0&sync_timestamp=1606973416764&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fexeca%2Fdownload%2Fexeca-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" integrity sha1-2NdrvBtVIX7RkP1t1J08d07PyNo= dependencies: cross-spawn "^5.0.1" @@ -3777,8 +3801,8 @@ execa@^0.8.0: execa@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/execa/download/execa-1.0.0.tgz?cache=0&sync_timestamp=1606973416764&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fexeca%2Fdownload%2Fexeca-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg= + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== dependencies: cross-spawn "^6.0.0" get-stream "^4.0.0" @@ -3790,8 +3814,8 @@ execa@^1.0.0: execa@^3.3.0: version "3.4.0" - resolved "https://registry.npm.taobao.org/execa/download/execa-3.4.0.tgz?cache=0&sync_timestamp=1606973416764&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fexeca%2Fdownload%2Fexeca-3.4.0.tgz#c08ed4550ef65d858fac269ffc8572446f37eb89" - integrity sha1-wI7UVQ72XYWPrCaf/IVyRG8364k= + resolved "https://registry.yarnpkg.com/execa/-/execa-3.4.0.tgz#c08ed4550ef65d858fac269ffc8572446f37eb89" + integrity sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g== dependencies: cross-spawn "^7.0.0" get-stream "^5.0.0" @@ -3806,7 +3830,7 @@ execa@^3.3.0: expand-brackets@^2.1.4: version "2.1.4" - resolved "https://registry.npm.taobao.org/expand-brackets/download/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" @@ -3819,8 +3843,8 @@ expand-brackets@^2.1.4: express@^4.16.3, express@^4.17.1: version "4.17.1" - resolved "https://registry.npm.taobao.org/express/download/express-4.17.1.tgz?cache=0&sync_timestamp=1598867231599&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fexpress%2Fdownload%2Fexpress-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha1-RJH8OGBc9R+GKdOcK10Cb5ikwTQ= + resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== dependencies: accepts "~1.3.7" array-flatten "1.1.1" @@ -3855,14 +3879,14 @@ express@^4.16.3, express@^4.17.1: extend-shallow@^2.0.1: version "2.0.1" - resolved "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" - resolved "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" @@ -3870,13 +3894,13 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@~3.0.2: version "3.0.2" - resolved "https://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo= + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== external-editor@^3.0.3: version "3.1.0" - resolved "https://registry.npm.taobao.org/external-editor/download/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha1-ywP3QL764D6k0oPK7SdBqD8zVJU= + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== dependencies: chardet "^0.7.0" iconv-lite "^0.4.24" @@ -3884,8 +3908,8 @@ external-editor@^3.0.3: extglob@^2.0.4: version "2.0.4" - resolved "https://registry.npm.taobao.org/extglob/download/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM= + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -3898,23 +3922,23 @@ extglob@^2.0.4: extsprintf@1.3.0: version "1.3.0" - resolved "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: version "1.4.0" - resolved "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= fast-deep-equal@^3.1.1: version "3.1.3" - resolved "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffast-deep-equal%2Fdownload%2Ffast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU= + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-glob@^2.2.6: version "2.2.7" - resolved "https://registry.npm.taobao.org/fast-glob/download/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" - integrity sha1-aVOFfDr6R1//ku5gFdUtpwpM050= + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" + integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== dependencies: "@mrmlnc/readdir-enhanced" "^2.2.1" "@nodelib/fs.stat" "^1.1.2" @@ -3925,61 +3949,61 @@ fast-glob@^2.2.6: fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM= + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@~2.0.6: version "2.0.6" - resolved "https://registry.npm.taobao.org/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= faye-websocket@^0.11.3: version "0.11.3" - resolved "https://registry.npm.taobao.org/faye-websocket/download/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" - integrity sha1-XA6aiWjokSwoZjn96XeosgnyUI4= + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" + integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== dependencies: websocket-driver ">=0.5.1" figgy-pudding@^3.5.1: version "3.5.2" - resolved "https://registry.npm.taobao.org/figgy-pudding/download/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" - integrity sha1-tO7oFIq7Adzx0aw0Nn1Z4S+mHW4= + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== figures@^3.0.0: version "3.2.0" - resolved "https://registry.npm.taobao.org/figures/download/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha1-YlwYvSk8YE3EqN2y/r8MiDQXRq8= + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== dependencies: escape-string-regexp "^1.0.5" file-entry-cache@^5.0.1: version "5.0.1" - resolved "https://registry.npm.taobao.org/file-entry-cache/download/file-entry-cache-5.0.1.tgz?cache=0&sync_timestamp=1604832267816&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffile-entry-cache%2Fdownload%2Ffile-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha1-yg9u+m3T1WEzP7FFFQZcL6/fQ5w= + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== dependencies: flat-cache "^2.0.1" file-loader@^4.2.0: version "4.3.0" - resolved "https://registry.npm.taobao.org/file-loader/download/file-loader-4.3.0.tgz?cache=0&sync_timestamp=1603817051330&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffile-loader%2Fdownload%2Ffile-loader-4.3.0.tgz#780f040f729b3d18019f20605f723e844b8a58af" - integrity sha1-eA8ED3KbPRgBnyBgX3I+hEuKWK8= + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-4.3.0.tgz#780f040f729b3d18019f20605f723e844b8a58af" + integrity sha512-aKrYPYjF1yG3oX0kWRrqrSMfgftm7oJW5M+m4owoldH5C51C0RkIwB++JbRvEW3IU6/ZG5n8UvEcdgwOt2UOWA== dependencies: loader-utils "^1.2.3" schema-utils "^2.5.0" file-uri-to-path@1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/file-uri-to-path/download/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90= + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== filesize@^3.6.1: version "3.6.1" - resolved "https://registry.npm.taobao.org/filesize/download/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" - integrity sha1-CQuz7gG2+AGoqL6Z0xcQs0Irsxc= + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" + integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== fill-range@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/fill-range/download/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" @@ -3989,15 +4013,15 @@ fill-range@^4.0.0: fill-range@^7.0.1: version "7.0.1" - resolved "https://registry.npm.taobao.org/fill-range/download/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha1-GRmmp8df44ssfHflGYU12prN2kA= + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: to-regex-range "^5.0.1" finalhandler@~1.1.2: version "1.1.2" - resolved "https://registry.npm.taobao.org/finalhandler/download/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha1-t+fQAP/RGTjQ/bBTUG9uur6fWH0= + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== dependencies: debug "2.6.9" encodeurl "~1.0.2" @@ -4009,7 +4033,7 @@ finalhandler@~1.1.2: find-cache-dir@^0.1.1: version "0.1.1" - resolved "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" integrity sha1-yN765XyKUqinhPnjHFfHQumToLk= dependencies: commondir "^1.0.1" @@ -4018,8 +4042,8 @@ find-cache-dir@^0.1.1: find-cache-dir@^2.1.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc= + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== dependencies: commondir "^1.0.1" make-dir "^2.0.0" @@ -4027,8 +4051,8 @@ find-cache-dir@^2.1.0: find-cache-dir@^3.0.0, find-cache-dir@^3.3.1: version "3.3.1" - resolved "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" - integrity sha1-ibM/rUpGcNqpT4Vff74x1thP6IA= + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== dependencies: commondir "^1.0.1" make-dir "^3.0.2" @@ -4036,7 +4060,7 @@ find-cache-dir@^3.0.0, find-cache-dir@^3.3.1: find-up@^1.0.0: version "1.1.2" - resolved "https://registry.npm.taobao.org/find-up/download/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= dependencies: path-exists "^2.0.0" @@ -4044,23 +4068,23 @@ find-up@^1.0.0: find-up@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha1-SRafHXmTQwZG2mHsxa41XCHJe3M= + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== dependencies: locate-path "^3.0.0" -find-up@^4.0.0, find-up@^4.1.0: +find-up@^4.0.0: version "4.1.0" - resolved "https://registry.npm.taobao.org/find-up/download/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha1-l6/n1s3AvFkoWEt8jXsW6KmqXRk= + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" path-exists "^4.0.0" flat-cache@^2.0.1: version "2.0.1" - resolved "https://registry.npm.taobao.org/flat-cache/download/flat-cache-2.0.1.tgz?cache=0&sync_timestamp=1604831928877&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fflat-cache%2Fdownload%2Fflat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha1-XSltbwS9pEpGMKMBQTvbwuwIXsA= + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== dependencies: flatted "^2.0.0" rimraf "2.6.3" @@ -4068,36 +4092,36 @@ flat-cache@^2.0.1: flatted@^2.0.0: version "2.0.2" - resolved "https://registry.npm.taobao.org/flatted/download/flatted-2.0.2.tgz?cache=0&sync_timestamp=1601444397688&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fflatted%2Fdownload%2Fflatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha1-RXWyHivO50NKqb5mL0t7X5wrUTg= + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== flush-write-stream@^1.0.0: version "1.1.1" - resolved "https://registry.npm.taobao.org/flush-write-stream/download/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" - integrity sha1-jdfYc6G6vCB9lOrQwuDkQnbr8ug= + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== dependencies: inherits "^2.0.3" readable-stream "^2.3.6" follow-redirects@^1.0.0, follow-redirects@^1.10.0: - version "1.13.1" - resolved "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.13.1.tgz?cache=0&sync_timestamp=1607917368794&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffollow-redirects%2Fdownload%2Ffollow-redirects-1.13.1.tgz#5f69b813376cee4fd0474a3aba835df04ab763b7" - integrity sha1-X2m4Ezds7k/QR0o6uoNd8Eq3Y7c= + version "1.13.3" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267" + integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA== for-in@^1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= forever-agent@~0.6.1: version "0.6.1" - resolved "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= form-data@~2.3.2: version "2.3.3" - resolved "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha1-3M5SwF9kTymManq5Nr1yTO/786Y= + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" combined-stream "^1.0.6" @@ -4105,24 +4129,24 @@ form-data@~2.3.2: forwarded@~0.1.2: version "0.1.2" - resolved "https://registry.npm.taobao.org/forwarded/download/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= fragment-cache@^0.2.1: version "0.2.1" - resolved "https://registry.npm.taobao.org/fragment-cache/download/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" - resolved "https://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= from2@^2.1.0: version "2.3.0" - resolved "https://registry.npm.taobao.org/from2/download/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= dependencies: inherits "^2.0.1" @@ -4130,8 +4154,8 @@ from2@^2.1.0: fs-extra@^7.0.1: version "7.0.1" - resolved "https://registry.npm.taobao.org/fs-extra/download/fs-extra-7.0.1.tgz?cache=0&sync_timestamp=1598867217764&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-extra%2Fdownload%2Ffs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha1-TxicRKoSO4lfcigE9V6iPq3DSOk= + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -4148,14 +4172,14 @@ fs-extra@^8.1.0: fs-minipass@^2.0.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/fs-minipass/download/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" - integrity sha1-f1A2/b8SxjwWkZDL5BmchSJx+fs= + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== dependencies: minipass "^3.0.0" fs-write-stream-atomic@^1.0.8: version "1.0.10" - resolved "https://registry.npm.taobao.org/fs-write-stream-atomic/download/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= dependencies: graceful-fs "^4.1.2" @@ -4165,53 +4189,53 @@ fs-write-stream-atomic@^1.0.8: fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.2.7: version "1.2.13" - resolved "https://registry.npm.taobao.org/fsevents/download/fsevents-1.2.13.tgz?cache=0&sync_timestamp=1609861413593&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffsevents%2Fdownload%2Ffsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg= + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== dependencies: bindings "^1.5.0" nan "^2.12.1" fsevents@~2.3.1: - version "2.3.1" - resolved "https://registry.npm.taobao.org/fsevents/download/fsevents-2.3.1.tgz?cache=0&sync_timestamp=1609861413593&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffsevents%2Fdownload%2Ffsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f" - integrity sha1-sgmrFMYQEmNsiGNQft9/tozFTp8= + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0= + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/functional-red-black-tree/download/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= generic-names@^2.0.1: version "2.0.1" - resolved "https://registry.npm.taobao.org/generic-names/download/generic-names-2.0.1.tgz?cache=0&sync_timestamp=1603542442076&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgeneric-names%2Fdownload%2Fgeneric-names-2.0.1.tgz#f8a378ead2ccaa7a34f0317b05554832ae41b872" - integrity sha1-+KN46tLMqno08DF7BVVIMq5BuHI= + resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-2.0.1.tgz#f8a378ead2ccaa7a34f0317b05554832ae41b872" + integrity sha512-kPCHWa1m9wGG/OwQpeweTwM/PYiQLrUIxXbt/P4Nic3LbGjCP0YwrALHW1uNLKZ0LIMg+RF+XRlj2ekT9ZlZAQ== dependencies: loader-utils "^1.1.0" -gensync@^1.0.0-beta.1: +gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.npm.taobao.org/gensync/download/gensync-1.0.0-beta.2.tgz?cache=0&sync_timestamp=1603829716561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgensync%2Fdownload%2Fgensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha1-MqbudsPX9S1GsrGuXZP+qFgKJeA= + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.npm.taobao.org/get-caller-file/download/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha1-T5RBKoLbMvNuOwuXQfipf+sDH34= + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.0: - version "1.0.2" - resolved "https://registry.npm.taobao.org/get-intrinsic/download/get-intrinsic-1.0.2.tgz?cache=0&sync_timestamp=1608274364558&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fget-intrinsic%2Fdownload%2Fget-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49" - integrity sha1-aCDaIm5QskiU4IhZRp3Gg2FUXUk= +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== dependencies: function-bind "^1.1.1" has "^1.0.3" @@ -4219,58 +4243,58 @@ get-intrinsic@^1.0.0: get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" - resolved "https://registry.npm.taobao.org/get-own-enumerable-property-symbols/download/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" - integrity sha1-tf3nfyLL4185C04ImSLFC85u9mQ= + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" + integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== get-stream@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/get-stream/download/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= get-stream@^4.0.0: version "4.1.0" - resolved "https://registry.npm.taobao.org/get-stream/download/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha1-wbJVV189wh1Zv8ec09K0axw6VLU= + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== dependencies: pump "^3.0.0" get-stream@^5.0.0: version "5.2.0" - resolved "https://registry.npm.taobao.org/get-stream/download/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha1-SWaheV7lrOZecGxLe+txJX1uItM= + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" - resolved "https://registry.npm.taobao.org/get-value/download/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= getpass@^0.1.1: version "0.1.7" - resolved "https://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= dependencies: assert-plus "^1.0.0" glob-parent@^3.1.0: version "3.1.0" - resolved "https://registry.npm.taobao.org/glob-parent/download/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" glob-parent@^5.0.0, glob-parent@~5.1.0: - version "5.1.1" - resolved "https://registry.npm.taobao.org/glob-parent/download/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha1-tsHvQXxOVmPqSY8cRa+saRa7wik= + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob-to-regexp@^0.3.0: version "0.3.0" - resolved "https://registry.npm.taobao.org/glob-to-regexp/download/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: @@ -4287,19 +4311,19 @@ glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: globals@^11.1.0: version "11.12.0" - resolved "https://registry.npm.taobao.org/globals/download/globals-11.12.0.tgz?cache=0&sync_timestamp=1608438431237&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglobals%2Fdownload%2Fglobals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4= + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^12.1.0: version "12.4.0" - resolved "https://registry.npm.taobao.org/globals/download/globals-12.4.0.tgz?cache=0&sync_timestamp=1608438431237&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglobals%2Fdownload%2Fglobals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" - integrity sha1-oYgTV2pBsAokqX5/gVkYwuGZJfg= + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== dependencies: type-fest "^0.8.1" globby@^6.1.0: version "6.1.0" - resolved "https://registry.npm.taobao.org/globby/download/globby-6.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglobby%2Fdownload%2Fglobby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" + resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= dependencies: array-union "^1.0.1" @@ -4310,7 +4334,7 @@ globby@^6.1.0: globby@^7.1.1: version "7.1.1" - resolved "https://registry.npm.taobao.org/globby/download/globby-7.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglobby%2Fdownload%2Fglobby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" + resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" integrity sha1-+yzP+UAfhgCUXfral0QMypcrhoA= dependencies: array-union "^1.0.1" @@ -4322,8 +4346,8 @@ globby@^7.1.1: globby@^9.2.0: version "9.2.0" - resolved "https://registry.npm.taobao.org/globby/download/globby-9.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglobby%2Fdownload%2Fglobby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" - integrity sha1-/QKacGxwPSm90XD0tts6P3p8tj0= + resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" + integrity sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg== dependencies: "@types/glob" "^7.1.1" array-union "^1.0.2" @@ -4335,54 +4359,59 @@ globby@^9.2.0: slash "^2.0.0" graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2: - version "4.2.4" - resolved "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz?cache=0&sync_timestamp=1598867272489&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgraceful-fs%2Fdownload%2Fgraceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" - integrity sha1-Ila94U02MpWMRl68ltxGfKB6Kfs= + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== gzip-size@^5.0.0: version "5.1.1" - resolved "https://registry.npm.taobao.org/gzip-size/download/gzip-size-5.1.1.tgz?cache=0&sync_timestamp=1605523224661&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgzip-size%2Fdownload%2Fgzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" - integrity sha1-y5vuaS+HwGErIyhAqHOQTkwTUnQ= + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" + integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== dependencies: duplexer "^0.1.1" pify "^4.0.1" handle-thing@^2.0.0: version "2.0.1" - resolved "https://registry.npm.taobao.org/handle-thing/download/handle-thing-2.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhandle-thing%2Fdownload%2Fhandle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" - integrity sha1-hX95zjWVgMNA1DCBzGSJcNC7I04= + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== har-schema@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.3: version "5.1.5" - resolved "https://registry.npm.taobao.org/har-validator/download/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha1-HwgDufjLIMD6E4It8ezds2veHv0= + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: ajv "^6.12.3" har-schema "^2.0.0" +has-bigints@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s= + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.npm.taobao.org/has-symbols/download/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha1-n1IUdYpEGWxAbZvXbOv4HsLdMeg= +has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== has-value@^0.3.1: version "0.3.1" - resolved "https://registry.npm.taobao.org/has-value/download/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" @@ -4391,7 +4420,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/has-value/download/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" @@ -4400,12 +4429,12 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" - resolved "https://registry.npm.taobao.org/has-values/download/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/has-values/download/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" @@ -4413,15 +4442,15 @@ has-values@^1.0.0: has@^1.0.0, has@^1.0.3: version "1.0.3" - resolved "https://registry.npm.taobao.org/has/download/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y= + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" hash-base@^3.0.0: version "3.1.0" - resolved "https://registry.npm.taobao.org/hash-base/download/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha1-VcOB2eBuHSmXqIO0o/3f5/DTrzM= + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== dependencies: inherits "^2.0.4" readable-stream "^3.6.0" @@ -4429,40 +4458,40 @@ hash-base@^3.0.0: hash-sum@^1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/hash-sum/download/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04" + resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04" integrity sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ= hash-sum@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/hash-sum/download/hash-sum-2.0.0.tgz#81d01bb5de8ea4a214ad5d6ead1b523460b0b45a" - integrity sha1-gdAbtd6OpKIUrV1urRtSNGCwtFo= + resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-2.0.0.tgz#81d01bb5de8ea4a214ad5d6ead1b523460b0b45a" + integrity sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg== hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" - resolved "https://registry.npm.taobao.org/hash.js/download/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I= + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" he@1.2.x, he@^1.1.0: version "1.2.0" - resolved "https://registry.npm.taobao.org/he/download/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha1-hK5l+n6vsWX922FWauFLrwVmTw8= + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== hex-color-regex@^1.1.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/hex-color-regex/download/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" - integrity sha1-TAb8y0YC/iYCs8k9+C1+fb8aio4= + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" + integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== highlight.js@^10.0.0: - version "10.5.0" - resolved "https://registry.npm.taobao.org/highlight.js/download/highlight.js-10.5.0.tgz#3f09fede6a865757378f2d9ebdcbc15ba268f98f" - integrity sha1-Pwn+3mqGV1c3jy2evcvBW6Jo+Y8= + version "10.6.0" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.6.0.tgz#0073aa71d566906965ba6e1b7be7b2682f5e18b6" + integrity sha512-8mlRcn5vk/r4+QcqerapwBYTe+iPL5ih6xrNylxrnBdHQiijDETfXX7VIxC3UiCRiINBJfANBAsPzAvRQj8RpQ== -hmac-drbg@^1.0.0: +hmac-drbg@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/hmac-drbg/download/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= dependencies: hash.js "^1.0.3" @@ -4471,17 +4500,17 @@ hmac-drbg@^1.0.0: hoopy@^0.1.4: version "0.1.4" - resolved "https://registry.npm.taobao.org/hoopy/download/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" - integrity sha1-YJIH1mEQADOpqUAq096mdzgcGx0= + resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" + integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== hosted-git-info@^2.1.4: version "2.8.8" - resolved "https://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.8.8.tgz?cache=0&sync_timestamp=1602801693111&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhosted-git-info%2Fdownload%2Fhosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" - integrity sha1-dTm9S8Hg4KiVgVouAmJCCxKFhIg= + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" + integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== hpack.js@^2.1.6: version "2.1.6" - resolved "https://registry.npm.taobao.org/hpack.js/download/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= dependencies: inherits "^2.0.1" @@ -4491,28 +4520,28 @@ hpack.js@^2.1.6: hsl-regex@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/hsl-regex/download/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= hsla-regex@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/hsla-regex/download/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= html-comment-regex@^1.1.0: version "1.1.2" - resolved "https://registry.npm.taobao.org/html-comment-regex/download/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" - integrity sha1-l9RoiutcgYhqNk+qDK0d2hTUM6c= + resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" + integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== html-entities@^1.3.1: version "1.4.0" - resolved "https://registry.npm.taobao.org/html-entities/download/html-entities-1.4.0.tgz?cache=0&sync_timestamp=1609232480862&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhtml-entities%2Fdownload%2Fhtml-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" - integrity sha1-z70bAdKvr5rcobEK59/6uYxx0tw= + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" + integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== html-minifier@^3.2.3: version "3.5.21" - resolved "https://registry.npm.taobao.org/html-minifier/download/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" - integrity sha1-0AQOBUcw41TbAIRjWTGUAVIS0gw= + resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" + integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA== dependencies: camel-case "3.0.x" clean-css "4.2.x" @@ -4524,17 +4553,17 @@ html-minifier@^3.2.3: html-tags@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/html-tags/download/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b" integrity sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos= html-tags@^3.1.0: version "3.1.0" - resolved "https://registry.npm.taobao.org/html-tags/download/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" - integrity sha1-e15vfmZen7QfMAB+2eDUHpf7IUA= + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" + integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== html-webpack-plugin@^3.2.0: version "3.2.0" - resolved "https://registry.npm.taobao.org/html-webpack-plugin/download/html-webpack-plugin-3.2.0.tgz?cache=0&sync_timestamp=1609777900471&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhtml-webpack-plugin%2Fdownload%2Fhtml-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b" integrity sha1-sBq71yOsqqeze2r0SS69oD2d03s= dependencies: html-minifier "^3.2.3" @@ -4547,8 +4576,8 @@ html-webpack-plugin@^3.2.0: htmlparser2@^3.10.1: version "3.10.1" - resolved "https://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.10.1.tgz?cache=0&sync_timestamp=1607396725165&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhtmlparser2%2Fdownload%2Fhtmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha1-vWedw/WYl7ajS7EHSchVu1OpOS8= + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== dependencies: domelementtype "^1.3.1" domhandler "^2.3.0" @@ -4559,13 +4588,13 @@ htmlparser2@^3.10.1: http-deceiver@^1.2.7: version "1.2.7" - resolved "https://registry.npm.taobao.org/http-deceiver/download/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= http-errors@1.7.2: version "1.7.2" - resolved "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha1-T1ApzxMjnzEDblsuVSkrz7zIXI8= + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== dependencies: depd "~1.1.2" inherits "2.0.3" @@ -4575,7 +4604,7 @@ http-errors@1.7.2: http-errors@~1.6.2: version "1.6.3" - resolved "https://registry.npm.taobao.org/http-errors/download/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= dependencies: depd "~1.1.2" @@ -4585,8 +4614,8 @@ http-errors@~1.6.2: http-errors@~1.7.2: version "1.7.3" - resolved "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha1-bGGeT5xgMIw4UZSYwU+7EKrOuwY= + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== dependencies: depd "~1.1.2" inherits "2.0.4" @@ -4596,23 +4625,34 @@ http-errors@~1.7.2: http-parser-js@>=0.5.1: version "0.5.3" - resolved "https://registry.npm.taobao.org/http-parser-js/download/http-parser-js-0.5.3.tgz?cache=0&sync_timestamp=1609539959333&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-parser-js%2Fdownload%2Fhttp-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" - integrity sha1-AdJwnHnUFpi7AdTezF6dpOSgM9k= + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" + integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== http-proxy-middleware@0.19.1: version "0.19.1" - resolved "https://registry.npm.taobao.org/http-proxy-middleware/download/http-proxy-middleware-0.19.1.tgz?cache=0&sync_timestamp=1602445328560&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-proxy-middleware%2Fdownload%2Fhttp-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" - integrity sha1-GDx9xKoUeRUDBkmMIQza+WCApDo= + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" + integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== dependencies: http-proxy "^1.17.0" is-glob "^4.0.0" lodash "^4.17.11" micromatch "^3.1.10" -http-proxy@^1.17.0: +http-proxy-middleware@^1.0.0: + version "1.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-1.0.6.tgz#0618557722f450375d3796d701a8ac5407b3b94e" + integrity sha512-NyL6ZB6cVni7pl+/IT2W0ni5ME00xR0sN27AQZZrpKn1b+qRh+mLbBxIq9Cq1oGfmTc7BUq4HB77mxwCaxAYNg== + dependencies: + "@types/http-proxy" "^1.17.4" + http-proxy "^1.18.1" + is-glob "^4.0.1" + lodash "^4.17.20" + micromatch "^4.0.2" + +http-proxy@^1.17.0, http-proxy@^1.18.1: version "1.18.1" - resolved "https://registry.npm.taobao.org/http-proxy/download/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha1-QBVB8FNIhLv5UmAzTnL4juOXZUk= + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== dependencies: eventemitter3 "^4.0.0" follow-redirects "^1.0.0" @@ -4620,7 +4660,7 @@ http-proxy@^1.17.0: http-signature@~1.2.0: version "1.2.0" - resolved "https://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz?cache=0&sync_timestamp=1600868478326&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-signature%2Fdownload%2Fhttp-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= dependencies: assert-plus "^1.0.0" @@ -4629,63 +4669,68 @@ http-signature@~1.2.0: https-browserify@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/https-browserify/download/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= human-signals@^1.1.1: version "1.1.1" - resolved "https://registry.npm.taobao.org/human-signals/download/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" - integrity sha1-xbHNFPUK6uCatsWf5jujOV/k36M= + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" - resolved "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1594184266261&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha1-ICK0sl+93CHS9SSXSkdKr+czkIs= + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" icss-replace-symbols@^1.1.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/icss-replace-symbols/download/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" + resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= icss-utils@^4.0.0, icss-utils@^4.1.1: version "4.1.1" - resolved "https://registry.npm.taobao.org/icss-utils/download/icss-utils-4.1.1.tgz?cache=0&sync_timestamp=1605801506037&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficss-utils%2Fdownload%2Ficss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" - integrity sha1-IRcLU3ie4nRHwvR91oMIFAP5pGc= + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== dependencies: postcss "^7.0.14" +icss-utils@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + ieee754@^1.1.4: version "1.2.1" - resolved "https://registry.npm.taobao.org/ieee754/download/ieee754-1.2.1.tgz?cache=0&sync_timestamp=1603838314962&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fieee754%2Fdownload%2Fieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha1-jrehCmP/8l0VpXsAFYbRd9Gw01I= + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== iferr@^0.1.5: version "0.1.5" - resolved "https://registry.npm.taobao.org/iferr/download/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= ignore@^3.3.5: version "3.3.10" - resolved "https://registry.npm.taobao.org/ignore/download/ignore-3.3.10.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fignore%2Fdownload%2Fignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - integrity sha1-Cpf7h2mG6AgcYxFg+PnziRV/AEM= + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== ignore@^4.0.3, ignore@^4.0.6: version "4.0.6" - resolved "https://registry.npm.taobao.org/ignore/download/ignore-4.0.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fignore%2Fdownload%2Fignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw= + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== import-cwd@^2.0.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/import-cwd/download/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" + resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= dependencies: import-from "^2.1.0" import-fresh@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/import-fresh/download/import-fresh-2.0.0.tgz?cache=0&sync_timestamp=1608469462038&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimport-fresh%2Fdownload%2Fimport-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= dependencies: caller-path "^2.0.0" @@ -4693,50 +4738,50 @@ import-fresh@^2.0.0: import-fresh@^3.0.0: version "3.3.0" - resolved "https://registry.npm.taobao.org/import-fresh/download/import-fresh-3.3.0.tgz?cache=0&sync_timestamp=1608469462038&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimport-fresh%2Fdownload%2Fimport-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha1-NxYsJfy566oublPVtNiM4X2eDCs= + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" import-from@^2.1.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/import-from/download/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" integrity sha1-M1238qev/VOqpHHUuAId7ja387E= dependencies: resolve-from "^3.0.0" import-local@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/import-local/download/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha1-VQcL44pZk88Y72236WH1vuXFoJ0= + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== dependencies: pkg-dir "^3.0.0" resolve-cwd "^2.0.0" imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.npm.taobao.org/imurmurhash/download/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/indent-string/download/indent-string-4.0.0.tgz?cache=0&sync_timestamp=1598869159256&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Findent-string%2Fdownload%2Findent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha1-Yk+PRJfWGbLZdoUx1Y9BIoVNclE= + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== indexes-of@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/indexes-of/download/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= infer-owner@^1.0.3, infer-owner@^1.0.4: version "1.0.4" - resolved "https://registry.npm.taobao.org/infer-owner/download/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha1-xM78qo5RBRwqQLos6KPScpWvlGc= + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" @@ -4744,23 +4789,23 @@ inflight@^1.0.4: inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" - resolved "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w= + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== inherits@2.0.1: version "2.0.1" - resolved "https://registry.npm.taobao.org/inherits/download/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= inherits@2.0.3: version "2.0.3" - resolved "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= inquirer@^7.0.0, inquirer@^7.1.0: version "7.3.3" - resolved "https://registry.npm.taobao.org/inquirer/download/inquirer-7.3.3.tgz?cache=0&sync_timestamp=1595471746471&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finquirer%2Fdownload%2Finquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" - integrity sha1-BNF2sq8Er8FXqD/XwQDpjuCq0AM= + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" + integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== dependencies: ansi-escapes "^4.2.1" chalk "^4.1.0" @@ -4778,102 +4823,114 @@ inquirer@^7.0.0, inquirer@^7.1.0: internal-ip@^4.3.0: version "4.3.0" - resolved "https://registry.npm.taobao.org/internal-ip/download/internal-ip-4.3.0.tgz?cache=0&sync_timestamp=1605885569376&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finternal-ip%2Fdownload%2Finternal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" - integrity sha1-hFRSuq2dLKO2nGNaE3rLmg2tCQc= + resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" + integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== dependencies: default-gateway "^4.2.0" ipaddr.js "^1.9.0" ip-regex@^2.1.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/ip-regex/download/ip-regex-2.1.0.tgz?cache=0&sync_timestamp=1601334296605&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fip-regex%2Fdownload%2Fip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= ip@^1.1.0, ip@^1.1.5: version "1.1.5" - resolved "https://registry.npm.taobao.org/ip/download/ip-1.1.5.tgz?cache=0&sync_timestamp=1598867191154&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fip%2Fdownload%2Fip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= ipaddr.js@1.9.1, ipaddr.js@^1.9.0: version "1.9.1" - resolved "https://registry.npm.taobao.org/ipaddr.js/download/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha1-v/OFQ+64mEglB5/zoqjmy9RngbM= + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== is-absolute-url@^2.0.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/is-absolute-url/download/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= is-absolute-url@^3.0.3: version "3.0.3" - resolved "https://registry.npm.taobao.org/is-absolute-url/download/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" - integrity sha1-lsaiK2ojkpsR6gr7GDbDatSl1pg= + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== is-accessor-descriptor@^0.1.6: version "0.1.6" - resolved "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY= + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-arguments@^1.0.4: version "1.1.0" - resolved "https://registry.npm.taobao.org/is-arguments/download/is-arguments-1.1.0.tgz?cache=0&sync_timestamp=1607117583816&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-arguments%2Fdownload%2Fis-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9" - integrity sha1-YjUwMd++4HzrNGVqa95Z7+yujdk= + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9" + integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg== dependencies: call-bind "^1.0.0" is-arrayish@^0.2.1: version "0.2.1" - resolved "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= is-arrayish@^0.3.1: version "0.3.2" - resolved "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha1-RXSirlb3qyBolvtDHq7tBm/fjwM= + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + +is-bigint@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.1.tgz#6923051dfcbc764278540b9ce0e6b3213aa5ebc2" + integrity sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg== is-binary-path@^1.0.0: version "1.0.1" - resolved "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk= + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" +is-boolean-object@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.0.tgz#e2aaad3a3a8fca34c28f6eee135b156ed2587ff0" + integrity sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA== + dependencies: + call-bind "^1.0.0" + is-buffer@^1.1.5: version "1.1.6" - resolved "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz?cache=0&sync_timestamp=1604429461527&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-buffer%2Fdownload%2Fis-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha1-76ouqdqg16suoTqXsritUf776L4= + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.4, is-callable@^1.2.2: - version "1.2.2" - resolved "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.2.tgz?cache=0&sync_timestamp=1600719278998&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" - integrity sha1-x8ZxXNItTdtI0+GZcCI6zquwgNk= +is-callable@^1.1.4, is-callable@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" + integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== is-ci@^1.0.10: version "1.2.1" - resolved "https://registry.npm.taobao.org/is-ci/download/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" - integrity sha1-43ecjuF/zPQoSI9uKBGH8uYyhBw= + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" + integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== dependencies: ci-info "^1.5.0" is-color-stop@^1.0.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/is-color-stop/download/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= dependencies: css-color-names "^0.0.4" @@ -4883,36 +4940,36 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" -is-core-module@^2.1.0: +is-core-module@^2.2.0: version "2.2.0" - resolved "https://registry.npm.taobao.org/is-core-module/download/is-core-module-2.2.0.tgz?cache=0&sync_timestamp=1606411565080&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-core-module%2Fdownload%2Fis-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" - integrity sha1-lwN+89UiJNhRY/VZeytj2a/tmBo= + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" + integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== dependencies: has "^1.0.3" is-data-descriptor@^0.1.4: version "0.1.4" - resolved "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc= + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: version "1.0.2" - resolved "https://registry.npm.taobao.org/is-date-object/download/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" - integrity sha1-vac28s2P0G0yhE53Q7+nSUw7/X4= + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== is-descriptor@^0.1.0: version "0.1.6" - resolved "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco= + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" is-data-descriptor "^0.1.4" @@ -4920,8 +4977,8 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw= + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" is-data-descriptor "^1.0.0" @@ -4929,52 +4986,52 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-directory@^0.3.1: version "0.3.1" - resolved "https://registry.npm.taobao.org/is-directory/download/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= is-docker@^2.0.0: version "2.1.1" - resolved "https://registry.npm.taobao.org/is-docker/download/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" - integrity sha1-QSWojkTkUNOE4JBH7eca3C0UQVY= + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" + integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw== is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" - resolved "https://registry.npm.taobao.org/is-extendable/download/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ= + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-fullwidth-code-point@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0= + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-glob@^3.1.0: version "3.1.0" - resolved "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz?cache=0&sync_timestamp=1598237815612&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-glob%2Fdownload%2Fis-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" - resolved "https://registry.npm.taobao.org/is-glob/download/is-glob-4.0.1.tgz?cache=0&sync_timestamp=1598237815612&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-glob%2Fdownload%2Fis-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw= + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== dependencies: is-extglob "^2.1.1" @@ -4983,158 +5040,169 @@ is-module@^1.0.0: resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= -is-negative-zero@^2.0.0: +is-negative-zero@^2.0.1: version "2.0.1" - resolved "https://registry.npm.taobao.org/is-negative-zero/download/is-negative-zero-2.0.1.tgz?cache=0&sync_timestamp=1607123132826&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-negative-zero%2Fdownload%2Fis-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha1-PedGwY3aIxkkGlNnWQjY92bxHCQ= + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + +is-number-object@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" + integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== is-number@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/is-number/download/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss= + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-obj@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/is-obj/download/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= is-obj@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/is-obj/download/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha1-Rz+wXZc3BeP9liBUUBjKjiLvSYI= + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== is-path-cwd@^2.0.0: version "2.2.0" - resolved "https://registry.npm.taobao.org/is-path-cwd/download/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha1-Z9Q7gmZKe1GR/ZEZEn6zAASKn9s= + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== is-path-in-cwd@^2.0.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/is-path-in-cwd/download/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" - integrity sha1-v+Lcomxp85cmWkAJljYCk1oFOss= + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" + integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== dependencies: is-path-inside "^2.1.0" is-path-inside@^2.1.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/is-path-inside/download/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" - integrity sha1-fJgQWH1lmkDSe8201WFuqwWUlLI= + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" + integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== dependencies: path-is-inside "^1.0.2" is-plain-obj@^1.0.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/is-plain-obj/download/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" - resolved "https://registry.npm.taobao.org/is-plain-object/download/is-plain-object-2.0.4.tgz?cache=0&sync_timestamp=1599667372314&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-plain-object%2Fdownload%2Fis-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc= + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" -is-regex@^1.0.4, is-regex@^1.1.1: - version "1.1.1" - resolved "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.1.tgz?cache=0&sync_timestamp=1596555709354&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-regex%2Fdownload%2Fis-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" - integrity sha1-xvmKrMVG9s7FRooHt7FTq1ZKV7k= +is-regex@^1.0.4, is-regex@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251" + integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg== dependencies: + call-bind "^1.0.2" has-symbols "^1.0.1" is-regexp@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/is-regexp/download/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= is-resolvable@^1.0.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/is-resolvable/download/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg= + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== is-stream@^1.1.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= is-stream@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/is-stream/download/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" - integrity sha1-venDJoDW+uBBKdasnZIc54FfeOM= + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== is-svg@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/is-svg/download/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" - integrity sha1-kyHb0pwhLlypnE+peUxxS8r6L3U= + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" + integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== dependencies: html-comment-regex "^1.1.0" -is-symbol@^1.0.2: +is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.3" - resolved "https://registry.npm.taobao.org/is-symbol/download/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" - integrity sha1-OOEBS55jKb4N6dJKQU/XRB7GGTc= + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== dependencies: has-symbols "^1.0.1" is-typedarray@~1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-windows@^1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/is-windows/download/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0= + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== is-wsl@^1.1.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/is-wsl/download/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= is-wsl@^2.1.1: version "2.2.0" - resolved "https://registry.npm.taobao.org/is-wsl/download/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha1-dKTHbnfKn9P5MvKQwX6jJs0VcnE= + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== dependencies: is-docker "^2.0.0" isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/isobject/download/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" - resolved "https://registry.npm.taobao.org/isobject/download/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isstream@~0.1.2: version "0.1.2" - resolved "https://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= javascript-stringify@^2.0.1: version "2.0.1" - resolved "https://registry.npm.taobao.org/javascript-stringify/download/javascript-stringify-2.0.1.tgz#6ef358035310e35d667c675ed63d3eb7c1aa19e5" - integrity sha1-bvNYA1MQ411mfGde1j0+t8GqGeU= + resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-2.0.1.tgz#6ef358035310e35d667c675ed63d3eb7c1aa19e5" + integrity sha512-yV+gqbd5vaOYjqlbk16EG89xB5udgjqQF3C5FAORDg4f/IS1Yc5ERCv5e/57yBcfJYw05V5JyIXabhwb75Xxow== jest-worker@^24.9.0: version "24.9.0" @@ -5146,116 +5214,116 @@ jest-worker@^24.9.0: jest-worker@^25.4.0: version "25.5.0" - resolved "https://registry.npm.taobao.org/jest-worker/download/jest-worker-25.5.0.tgz?cache=0&sync_timestamp=1607352897825&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-worker%2Fdownload%2Fjest-worker-25.5.0.tgz#2611d071b79cea0f43ee57a3d118593ac1547db1" - integrity sha1-JhHQcbec6g9D7lej0RhZOsFUfbE= + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.5.0.tgz#2611d071b79cea0f43ee57a3d118593ac1547db1" + integrity sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw== dependencies: merge-stream "^2.0.0" supports-color "^7.0.0" js-message@1.0.7: version "1.0.7" - resolved "https://registry.npm.taobao.org/js-message/download/js-message-1.0.7.tgz#fbddd053c7a47021871bb8b2c95397cc17c20e47" - integrity sha1-+93QU8ekcCGHG7iyyVOXzBfCDkc= + resolved "https://registry.yarnpkg.com/js-message/-/js-message-1.0.7.tgz#fbddd053c7a47021871bb8b2c95397cc17c20e47" + integrity sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA== js-queue@2.0.2: version "2.0.2" - resolved "https://registry.npm.taobao.org/js-queue/download/js-queue-2.0.2.tgz?cache=0&sync_timestamp=1605129253735&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjs-queue%2Fdownload%2Fjs-queue-2.0.2.tgz#0be590338f903b36c73d33c31883a821412cd482" - integrity sha1-C+WQM4+QOzbHPTPDGIOoIUEs1II= + resolved "https://registry.yarnpkg.com/js-queue/-/js-queue-2.0.2.tgz#0be590338f903b36c73d33c31883a821412cd482" + integrity sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA== dependencies: easy-stack "^1.0.1" js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/js-tokens/download/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha1-GSA/tZmR35jjoocFDUZHzerzJJk= + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.13.1: version "3.14.1" - resolved "https://registry.npm.taobao.org/js-yaml/download/js-yaml-3.14.1.tgz?cache=0&sync_timestamp=1609680103034&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjs-yaml%2Fdownload%2Fjs-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha1-2ugS/bOCX6MGYJqHFzg8UMNqBTc= + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" esprima "^4.0.0" jsbn@~0.1.0: version "0.1.1" - resolved "https://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.npm.taobao.org/jsesc/download/jsesc-2.5.2.tgz?cache=0&sync_timestamp=1603891215549&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsesc%2Fdownload%2Fjsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q= + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== jsesc@~0.5.0: version "0.5.0" - resolved "https://registry.npm.taobao.org/jsesc/download/jsesc-0.5.0.tgz?cache=0&sync_timestamp=1603891215549&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsesc%2Fdownload%2Fjsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/json-parse-better-errors/download/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk= + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== json-parse-even-better-errors@^2.3.0: version "2.3.1" - resolved "https://registry.npm.taobao.org/json-parse-even-better-errors/download/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha1-fEeAWpQxmSjgV3dAXcEuH3pO4C0= + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz?cache=0&sync_timestamp=1607998264311&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-schema-traverse%2Fdownload%2Fjson-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha1-afaofZUTq4u4/mO9sJecRI5oRmA= + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema@0.2.3: version "0.2.3" - resolved "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz?cache=0&sync_timestamp=1609553838875&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-schema%2Fdownload%2Fjson-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/json-stable-stringify-without-jsonify/download/json-stable-stringify-without-jsonify-1.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-stable-stringify-without-jsonify%2Fdownload%2Fjson-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= json-stringify-safe@~5.0.1: version "5.0.1" - resolved "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json3@^3.3.3: version "3.3.3" - resolved "https://registry.npm.taobao.org/json3/download/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" - integrity sha1-f8EON1/FrkLEcFpcwKpvYr4wW4E= + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" + integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== json5@^0.5.0: version "0.5.1" - resolved "https://registry.npm.taobao.org/json5/download/json5-0.5.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= json5@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4= + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== dependencies: minimist "^1.2.0" json5@^2.1.2: - version "2.1.3" - resolved "https://registry.npm.taobao.org/json5/download/json5-2.1.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson5%2Fdownload%2Fjson5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" - integrity sha1-ybD3+pIzv+WAf+ZvzzpWF+1ZfUM= + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== dependencies: minimist "^1.2.5" jsonfile@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz?cache=0&sync_timestamp=1604161824632&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsonfile%2Fdownload%2Fjsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= optionalDependencies: graceful-fs "^4.1.6" jsprim@^1.2.2: version "1.4.1" - resolved "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: assert-plus "1.0.0" @@ -5265,51 +5333,51 @@ jsprim@^1.2.2: killable@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/killable/download/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" - integrity sha1-TIzkQRh6Bhx0dPuHygjipjgZSJI= + resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" + integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" - resolved "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/kind-of/download/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" - resolved "https://registry.npm.taobao.org/kind-of/download/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha1-cpyR4thXt6QZofmqZWhcTDP1hF0= + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.3" - resolved "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0= + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== launch-editor-middleware@^2.2.1: version "2.2.1" - resolved "https://registry.npm.taobao.org/launch-editor-middleware/download/launch-editor-middleware-2.2.1.tgz#e14b07e6c7154b0a4b86a0fd345784e45804c157" - integrity sha1-4UsH5scVSwpLhqD9NFeE5FgEwVc= + resolved "https://registry.yarnpkg.com/launch-editor-middleware/-/launch-editor-middleware-2.2.1.tgz#e14b07e6c7154b0a4b86a0fd345784e45804c157" + integrity sha512-s0UO2/gEGiCgei3/2UN3SMuUj1phjQN8lcpnvgLSz26fAzNWPQ6Nf/kF5IFClnfU2ehp6LrmKdMU/beveO+2jg== dependencies: launch-editor "^2.2.1" launch-editor@^2.2.1: version "2.2.1" - resolved "https://registry.npm.taobao.org/launch-editor/download/launch-editor-2.2.1.tgz#871b5a3ee39d6680fcc26d37930b6eeda89db0ca" - integrity sha1-hxtaPuOdZoD8wm03kwtu7aidsMo= + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.2.1.tgz#871b5a3ee39d6680fcc26d37930b6eeda89db0ca" + integrity sha512-On+V7K2uZK6wK7x691ycSUbLD/FyKKelArkbaAMSSJU8JmqmhwN2+mnJDNINuJWSrh2L0kDk+ZQtbC/gOWUwLw== dependencies: chalk "^2.3.0" shell-quote "^1.6.1" levn@^0.3.0, levn@~0.3.0: version "0.3.0" - resolved "https://registry.npm.taobao.org/levn/download/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= dependencies: prelude-ls "~1.1.2" @@ -5317,25 +5385,25 @@ levn@^0.3.0, levn@~0.3.0: lines-and-columns@^1.1.6: version "1.1.6" - resolved "https://registry.npm.taobao.org/lines-and-columns/download/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= loader-fs-cache@^1.0.0: version "1.0.3" - resolved "https://registry.npm.taobao.org/loader-fs-cache/download/loader-fs-cache-1.0.3.tgz#f08657646d607078be2f0a032f8bd69dd6f277d9" - integrity sha1-8IZXZG1gcHi+LwoDL4vWndbyd9k= + resolved "https://registry.yarnpkg.com/loader-fs-cache/-/loader-fs-cache-1.0.3.tgz#f08657646d607078be2f0a032f8bd69dd6f277d9" + integrity sha512-ldcgZpjNJj71n+2Mf6yetz+c9bM4xpKtNds4LbqXzU/PTdeAX0g3ytnU1AJMEcTk2Lex4Smpe3Q/eCTsvUBxbA== dependencies: find-cache-dir "^0.1.1" mkdirp "^0.5.1" loader-runner@^2.3.1, loader-runner@^2.4.0: version "2.4.0" - resolved "https://registry.npm.taobao.org/loader-runner/download/loader-runner-2.4.0.tgz?cache=0&sync_timestamp=1610027908268&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floader-runner%2Fdownload%2Floader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" - integrity sha1-7UcGa/5TTX6ExMe5mYwqdWB9k1c= + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== loader-utils@^0.2.16: version "0.2.17" - resolved "https://registry.npm.taobao.org/loader-utils/download/loader-utils-0.2.17.tgz?cache=0&sync_timestamp=1598867216219&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floader-utils%2Fdownload%2Floader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= dependencies: big.js "^3.1.3" @@ -5345,8 +5413,8 @@ loader-utils@^0.2.16: loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" - resolved "https://registry.npm.taobao.org/loader-utils/download/loader-utils-1.4.0.tgz?cache=0&sync_timestamp=1598867216219&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floader-utils%2Fdownload%2Floader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha1-xXm140yzSxp07cbB+za/o3HVphM= + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" @@ -5354,8 +5422,8 @@ loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4 loader-utils@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/loader-utils/download/loader-utils-2.0.0.tgz?cache=0&sync_timestamp=1598867216219&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floader-utils%2Fdownload%2Floader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" - integrity sha1-5MrOW4FtQloWa18JfhDNErNgZLA= + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" @@ -5363,47 +5431,52 @@ loader-utils@^2.0.0: locate-path@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4= + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== dependencies: p-locate "^3.0.0" path-exists "^3.0.0" locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha1-Gvujlq/WdqbUJQTQpno6frn2KqA= + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" lodash._reinterpolate@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/lodash._reinterpolate/download/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= lodash.camelcase@^4.3.0: version "4.3.0" - resolved "https://registry.npm.taobao.org/lodash.camelcase/download/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + lodash.defaultsdeep@^4.6.1: version "4.6.1" - resolved "https://registry.npm.taobao.org/lodash.defaultsdeep/download/lodash.defaultsdeep-4.6.1.tgz?cache=0&sync_timestamp=1562718717933&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash.defaultsdeep%2Fdownload%2Flodash.defaultsdeep-4.6.1.tgz#512e9bd721d272d94e3d3a63653fa17516741ca6" - integrity sha1-US6b1yHSctlOPTpjZT+hdRZ0HKY= + resolved "https://registry.yarnpkg.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz#512e9bd721d272d94e3d3a63653fa17516741ca6" + integrity sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA== lodash.kebabcase@^4.1.1: version "4.1.1" - resolved "https://registry.npm.taobao.org/lodash.kebabcase/download/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" + resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY= lodash.mapvalues@^4.6.0: version "4.6.0" - resolved "https://registry.npm.taobao.org/lodash.mapvalues/download/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" + resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" integrity sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw= lodash.memoize@^4.1.2: version "4.1.2" - resolved "https://registry.npm.taobao.org/lodash.memoize/download/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= lodash.template@^4.5.0: @@ -5416,103 +5489,103 @@ lodash.template@^4.5.0: lodash.templatesettings@^4.0.0: version "4.2.0" - resolved "https://registry.npm.taobao.org/lodash.templatesettings/download/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" - integrity sha1-5IExDwSdPPbUfpEq0JMTsVTw+zM= + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== dependencies: lodash._reinterpolate "^3.0.0" lodash.transform@^4.6.0: version "4.6.0" - resolved "https://registry.npm.taobao.org/lodash.transform/download/lodash.transform-4.6.0.tgz#12306422f63324aed8483d3f38332b5f670547a0" + resolved "https://registry.yarnpkg.com/lodash.transform/-/lodash.transform-4.6.0.tgz#12306422f63324aed8483d3f38332b5f670547a0" integrity sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A= lodash.uniq@^4.5.0: version "4.5.0" - resolved "https://registry.npm.taobao.org/lodash.uniq/download/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.3: - version "4.17.20" - resolved "https://registry.npm.taobao.org/lodash/download/lodash-4.17.20.tgz?cache=0&sync_timestamp=1598867216316&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI= + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== log-symbols@^2.2.0: version "2.2.0" - resolved "https://registry.npm.taobao.org/log-symbols/download/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo= + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== dependencies: chalk "^2.0.1" loglevel@^1.6.8: version "1.7.1" - resolved "https://registry.npm.taobao.org/loglevel/download/loglevel-1.7.1.tgz?cache=0&sync_timestamp=1606312226891&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floglevel%2Fdownload%2Floglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" - integrity sha1-AF/eL15uRwaPk1/yhXPhJe9y8Zc= + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" + integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== lower-case@^1.1.1: version "1.1.4" - resolved "https://registry.npm.taobao.org/lower-case/download/lower-case-1.1.4.tgz?cache=0&sync_timestamp=1606867791834&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flower-case%2Fdownload%2Flower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= lru-cache@^4.0.1, lru-cache@^4.1.2: version "4.1.5" - resolved "https://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80= + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" lru-cache@^5.1.1: version "5.1.1" - resolved "https://registry.npm.taobao.org/lru-cache/download/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA= + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.npm.taobao.org/lru-cache/download/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha1-bW/mVw69lqr5D8rR2vo7JWbbOpQ= + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" magic-string@^0.25.0, magic-string@^0.25.7: version "0.25.7" - resolved "https://registry.npm.taobao.org/magic-string/download/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" - integrity sha1-P0l9b9NMZpxnmNy4IfLvMfVEUFE= + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" + integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== dependencies: sourcemap-codec "^1.4.4" make-dir@^2.0.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU= + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== dependencies: pify "^4.0.1" semver "^5.6.0" make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" - resolved "https://registry.npm.taobao.org/make-dir/download/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha1-QV6WcEazp/HRhSd9hKpYIDcmoT8= + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" map-cache@^0.2.2: version "0.2.2" - resolved "https://registry.npm.taobao.org/map-cache/download/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-visit@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/map-visit/download/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" md5.js@^1.3.4: version "1.3.5" - resolved "https://registry.npm.taobao.org/md5.js/download/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8= + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -5520,22 +5593,22 @@ md5.js@^1.3.4: mdn-data@2.0.14: version "2.0.14" - resolved "https://registry.npm.taobao.org/mdn-data/download/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha1-cRP8QoGRfWPOKbQ0RvcB5owlulA= + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== mdn-data@2.0.4: version "2.0.4" - resolved "https://registry.npm.taobao.org/mdn-data/download/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" - integrity sha1-aZs8OKxvHXKAkaZGULZdOIUC/Vs= + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== media-typer@0.3.0: version "0.3.0" - resolved "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= memory-fs@^0.4.1: version "0.4.1" - resolved "https://registry.npm.taobao.org/memory-fs/download/memory-fs-0.4.1.tgz?cache=0&sync_timestamp=1598867216233&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmemory-fs%2Fdownload%2Fmemory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= dependencies: errno "^0.1.3" @@ -5543,43 +5616,43 @@ memory-fs@^0.4.1: memory-fs@^0.5.0: version "0.5.0" - resolved "https://registry.npm.taobao.org/memory-fs/download/memory-fs-0.5.0.tgz?cache=0&sync_timestamp=1598867216233&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmemory-fs%2Fdownload%2Fmemory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" - integrity sha1-MkwBKIuIZSlm0WHbd4OHIIRajjw= + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== dependencies: errno "^0.1.3" readable-stream "^2.0.1" merge-descriptors@1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/merge-descriptors/download/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= merge-source-map@^1.1.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/merge-source-map/download/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" - integrity sha1-L93n5gIJOfcJBqaPLXrmheTIxkY= + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" + integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== dependencies: source-map "^0.6.1" merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/merge-stream/download/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha1-UoI2KaFN0AyXcPtq1H3GMQ8sH2A= + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== merge2@^1.2.3: version "1.4.1" - resolved "https://registry.npm.taobao.org/merge2/download/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha1-Q2iJL4hekHRVpv19xVwMnUBJkK4= + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== methods@~1.1.2: version "1.1.2" - resolved "https://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" - resolved "https://registry.npm.taobao.org/micromatch/download/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha1-cIWbyVyYQJUvNZoGij/En57PrCM= + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -5595,50 +5668,58 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + miller-rabin@^4.0.0: version "4.0.1" - resolved "https://registry.npm.taobao.org/miller-rabin/download/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha1-8IA1HIZbDcViqEYpZtqlNUPHik0= + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.45.0, "mime-db@>= 1.43.0 < 2": - version "1.45.0" - resolved "https://registry.npm.taobao.org/mime-db/download/mime-db-1.45.0.tgz?cache=0&sync_timestamp=1600831202365&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-db%2Fdownload%2Fmime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" - integrity sha1-zO7aIczXw6dF66LezVXUtz54eeo= +mime-db@1.46.0, "mime-db@>= 1.43.0 < 2": + version "1.46.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.46.0.tgz#6267748a7f799594de3cbc8cde91def349661cee" + integrity sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ== mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.28" - resolved "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.28.tgz?cache=0&sync_timestamp=1609562382117&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-types%2Fdownload%2Fmime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" - integrity sha1-EWDEdX6rLFNjiI4AUnPs950qDs0= + version "2.1.29" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.29.tgz#1d4ab77da64b91f5f72489df29236563754bb1b2" + integrity sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ== dependencies: - mime-db "1.45.0" + mime-db "1.46.0" mime@1.6.0: version "1.6.0" - resolved "https://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz?cache=0&sync_timestamp=1608084195308&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime%2Fdownload%2Fmime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE= + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mime@^2.4.4: - version "2.4.7" - resolved "https://registry.npm.taobao.org/mime/download/mime-2.4.7.tgz?cache=0&sync_timestamp=1608084195308&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime%2Fdownload%2Fmime-2.4.7.tgz#962aed9be0ed19c91fd7dc2ece5d7f4e89a90d74" - integrity sha1-lirtm+DtGckf19wuzl1/TompDXQ= + version "2.5.2" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" + integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== mimic-fn@^1.0.0: version "1.2.0" - resolved "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI= + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== mimic-fn@^2.1.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs= + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== mini-css-extract-plugin@^0.9.0: version "0.9.0" - resolved "https://registry.npm.taobao.org/mini-css-extract-plugin/download/mini-css-extract-plugin-0.9.0.tgz?cache=0&sync_timestamp=1607647997292&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmini-css-extract-plugin%2Fdownload%2Fmini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e" - integrity sha1-R/LPB6oWWrNXM7H8l9TEbAVkM54= + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e" + integrity sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A== dependencies: loader-utils "^1.1.0" normalize-url "1.9.1" @@ -5647,58 +5728,58 @@ mini-css-extract-plugin@^0.9.0: minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/minimalistic-assert/download/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc= + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: +minimalistic-crypto-utils@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/minimalistic-crypto-utils/download/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= minimatch@^3.0.4: version "3.0.4" - resolved "https://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimatch%2Fdownload%2Fminimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM= + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" - resolved "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI= + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== minipass-collect@^1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/minipass-collect/download/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" - integrity sha1-IrgTv3Rdxu26JXa5QAIq1u3Ixhc= + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== dependencies: minipass "^3.0.0" minipass-flush@^1.0.5: version "1.0.5" - resolved "https://registry.npm.taobao.org/minipass-flush/download/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" - integrity sha1-gucTXX6JpQ/+ZGEKeHlTxMTLs3M= + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== dependencies: minipass "^3.0.0" minipass-pipeline@^1.2.2: version "1.2.4" - resolved "https://registry.npm.taobao.org/minipass-pipeline/download/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" - integrity sha1-aEcveXEcCEZXwGfFxq2Tzd6oIUw= + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== dependencies: minipass "^3.0.0" minipass@^3.0.0, minipass@^3.1.1: version "3.1.3" - resolved "https://registry.npm.taobao.org/minipass/download/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" - integrity sha1-fUL/HzljVILhX5zbUxhN7r1YFf0= + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" + integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== dependencies: yallist "^4.0.0" mississippi@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/mississippi/download/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" - integrity sha1-6goykfl+C16HdrNj1fChLZTGcCI= + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== dependencies: concat-stream "^1.5.0" duplexify "^3.4.2" @@ -5713,16 +5794,16 @@ mississippi@^3.0.0: mixin-deep@^1.2.0: version "1.3.2" - resolved "https://registry.npm.taobao.org/mixin-deep/download/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha1-ESC0PcNZp4Xc5ltVuC4lfM9HlWY= + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" - resolved "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz?cache=0&sync_timestamp=1598867243878&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8= + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: minimist "^1.2.5" @@ -5733,7 +5814,7 @@ moment@^2.29.1: move-concurrently@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= dependencies: aproba "^1.1.1" @@ -5745,46 +5826,46 @@ move-concurrently@^1.0.1: ms@2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433843106&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@2.1.1: version "2.1.1" - resolved "https://registry.npm.taobao.org/ms/download/ms-2.1.1.tgz?cache=0&sync_timestamp=1607433843106&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo= + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== ms@2.1.2: version "2.1.2" - resolved "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&sync_timestamp=1607433843106&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk= + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== ms@^2.1.1: version "2.1.3" - resolved "https://registry.npm.taobao.org/ms/download/ms-2.1.3.tgz?cache=0&sync_timestamp=1607433843106&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha1-V0yBOM4dK1hh8LRFedut1gxmFbI= + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== multicast-dns-service-types@^1.1.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/multicast-dns-service-types/download/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" + resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= multicast-dns@^6.0.1: version "6.2.3" - resolved "https://registry.npm.taobao.org/multicast-dns/download/multicast-dns-6.2.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmulticast-dns%2Fdownload%2Fmulticast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" - integrity sha1-oOx72QVcQoL3kMPIL04o2zsxsik= + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" + integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== dependencies: dns-packet "^1.3.1" thunky "^1.0.2" mute-stream@0.0.8: version "0.0.8" - resolved "https://registry.npm.taobao.org/mute-stream/download/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha1-FjDEKyJR/4HiooPelqVJfqkuXg0= + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== mz@^2.4.0: version "2.7.0" - resolved "https://registry.npm.taobao.org/mz/download/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - integrity sha1-lQCAV6Vsr63CvGPd5/n/aVWUjjI= + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== dependencies: any-promise "^1.0.0" object-assign "^4.0.1" @@ -5792,13 +5873,18 @@ mz@^2.4.0: nan@^2.12.1: version "2.14.2" - resolved "https://registry.npm.taobao.org/nan/download/nan-2.14.2.tgz?cache=0&sync_timestamp=1602591595921&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnan%2Fdownload%2Fnan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" - integrity sha1-9TdkAGlRaPTMaUrJOT0MlYXu6hk= + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" + integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== + +nanoid@^3.1.20: + version "3.1.22" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844" + integrity sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ== nanomatch@^1.2.9: version "1.2.13" - resolved "https://registry.npm.taobao.org/nanomatch/download/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk= + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -5814,28 +5900,28 @@ nanomatch@^1.2.9: natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.npm.taobao.org/natural-compare/download/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= negotiator@0.6.2: version "0.6.2" - resolved "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs= + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: version "2.6.2" - resolved "https://registry.npm.taobao.org/neo-async/download/neo-async-2.6.2.tgz?cache=0&sync_timestamp=1594317444539&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fneo-async%2Fdownload%2Fneo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha1-tKr7k+OustgXTKU88WOrfXMIMF8= + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== nice-try@^1.0.4: version "1.0.5" - resolved "https://registry.npm.taobao.org/nice-try/download/nice-try-1.0.5.tgz?cache=0&sync_timestamp=1602353393713&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnice-try%2Fdownload%2Fnice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y= + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== no-case@^2.2.0: version "2.3.2" - resolved "https://registry.npm.taobao.org/no-case/download/no-case-2.3.2.tgz?cache=0&sync_timestamp=1606869671099&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fno-case%2Fdownload%2Fno-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" - integrity sha1-YLgTOWvjmz8SiKTB7V0efSi0ZKw= + resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" + integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== dependencies: lower-case "^1.1.1" @@ -5846,13 +5932,13 @@ node-fetch@^2.6.1: node-forge@^0.10.0: version "0.10.0" - resolved "https://registry.npm.taobao.org/node-forge/download/node-forge-0.10.0.tgz?cache=0&sync_timestamp=1599010928186&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-forge%2Fdownload%2Fnode-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" - integrity sha1-Mt6ir7Ppkm8C7lzoeUkCaRpna/M= + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" + integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== node-ipc@^9.1.1: - version "9.1.3" - resolved "https://registry.npm.taobao.org/node-ipc/download/node-ipc-9.1.3.tgz?cache=0&sync_timestamp=1605200009302&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-ipc%2Fdownload%2Fnode-ipc-9.1.3.tgz#1df3f069d103184ae9127fa885dbdaea56a4436f" - integrity sha1-HfPwadEDGErpEn+ohdva6lakQ28= + version "9.1.4" + resolved "https://registry.yarnpkg.com/node-ipc/-/node-ipc-9.1.4.tgz#2acf962681afdac2602876d98fe6434d54d9bd3c" + integrity sha512-A+f0mn2KxUt1uRTSd5ktxQUsn2OEhj5evo7NUi/powBzMSZ0vocdzDjlq9QN2v3LH6CJi3e5xAenpZ1QwU5A8g== dependencies: event-pubsub "4.3.0" js-message "1.0.7" @@ -5860,8 +5946,8 @@ node-ipc@^9.1.1: node-libs-browser@^2.2.1: version "2.2.1" - resolved "https://registry.npm.taobao.org/node-libs-browser/download/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha1-tk9RPRgzhiX5A0bSew0jXmMfZCU= + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== dependencies: assert "^1.1.1" browserify-zlib "^0.2.0" @@ -5887,15 +5973,15 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-releases@^1.1.69: - version "1.1.69" - resolved "https://registry.npm.taobao.org/node-releases/download/node-releases-1.1.69.tgz?cache=0&sync_timestamp=1609789966075&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-releases%2Fdownload%2Fnode-releases-1.1.69.tgz#3149dbde53b781610cd8b486d62d86e26c3725f6" - integrity sha1-MUnb3lO3gWEM2LSG1i2G4mw3JfY= +node-releases@^1.1.70: + version "1.1.71" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" + integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== normalize-package-data@^2.5.0: version "2.5.0" - resolved "https://registry.npm.taobao.org/normalize-package-data/download/normalize-package-data-2.5.0.tgz?cache=0&sync_timestamp=1602547513139&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnormalize-package-data%2Fdownload%2Fnormalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg= + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== dependencies: hosted-git-info "^2.1.4" resolve "^1.10.0" @@ -5904,29 +5990,29 @@ normalize-package-data@^2.5.0: normalize-path@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/normalize-path/download/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" integrity sha1-MtDkcvkf80VwHBWoMRAY07CpA3k= normalize-path@^2.1.1: version "2.1.1" - resolved "https://registry.npm.taobao.org/normalize-path/download/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU= + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== normalize-range@^0.1.2: version "0.1.2" - resolved "https://registry.npm.taobao.org/normalize-range/download/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= normalize-url@1.9.1: version "1.9.1" - resolved "https://registry.npm.taobao.org/normalize-url/download/normalize-url-1.9.1.tgz?cache=0&sync_timestamp=1602432435724&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnormalize-url%2Fdownload%2Fnormalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= dependencies: object-assign "^4.0.1" @@ -5936,48 +6022,48 @@ normalize-url@1.9.1: normalize-url@^3.0.0: version "3.3.0" - resolved "https://registry.npm.taobao.org/normalize-url/download/normalize-url-3.3.0.tgz?cache=0&sync_timestamp=1602432435724&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnormalize-url%2Fdownload%2Fnormalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" - integrity sha1-suHE3E98bVd0PfczpPWXjRhlBVk= + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" + integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== npm-run-path@^2.0.0: version "2.0.2" - resolved "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= dependencies: path-key "^2.0.0" npm-run-path@^4.0.0: version "4.0.1" - resolved "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha1-t+zR5e1T2o43pV4cImnguX7XSOo= + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: path-key "^3.0.0" nth-check@^1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/nth-check/download/nth-check-1.0.2.tgz?cache=0&sync_timestamp=1606861164153&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnth-check%2Fdownload%2Fnth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha1-sr0pXDfj3VijvwcAN2Zjuk2c8Fw= + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== dependencies: boolbase "~1.0.0" num2fraction@^1.2.2: version "1.2.2" - resolved "https://registry.npm.taobao.org/num2fraction/download/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= oauth-sign@~0.9.0: version "0.9.0" - resolved "https://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU= + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" - resolved "https://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject-assign%2Fdownload%2Fobject-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" - resolved "https://registry.npm.taobao.org/object-copy/download/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" @@ -5986,38 +6072,38 @@ object-copy@^0.1.0: object-hash@^1.1.4: version "1.3.1" - resolved "https://registry.npm.taobao.org/object-hash/download/object-hash-1.3.1.tgz?cache=0&sync_timestamp=1608921384686&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject-hash%2Fdownload%2Fobject-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df" - integrity sha1-/eRSCYqVHLFF8Dm7fUVUSd3BJt8= + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df" + integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== -object-inspect@^1.8.0: +object-inspect@^1.9.0: version "1.9.0" - resolved "https://registry.npm.taobao.org/object-inspect/download/object-inspect-1.9.0.tgz?cache=0&sync_timestamp=1606804315827&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject-inspect%2Fdownload%2Fobject-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" - integrity sha1-yQUh104RJ7ZyZt7TOUrWEWmGUzo= + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" + integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== object-is@^1.0.1: - version "1.1.4" - resolved "https://registry.npm.taobao.org/object-is/download/object-is-1.1.4.tgz?cache=0&sync_timestamp=1606460519526&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject-is%2Fdownload%2Fobject-is-1.1.4.tgz#63d6c83c00a43f4cbc9434eb9757c8a5b8565068" - integrity sha1-Y9bIPACkP0y8lDTrl1fIpbhWUGg= + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.npm.taobao.org/object-keys/download/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha1-HEfyct8nfzsdrwYWd9nILiMixg4= + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object-visit@^1.0.0: version "1.0.1" - resolved "https://registry.npm.taobao.org/object-visit/download/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" -object.assign@^4.1.0, object.assign@^4.1.1: +object.assign@^4.1.0, object.assign@^4.1.2: version "4.1.2" - resolved "https://registry.npm.taobao.org/object.assign/download/object.assign-4.1.2.tgz?cache=0&sync_timestamp=1604117098938&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject.assign%2Fdownload%2Fobject.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha1-DtVKNC7Os3s4/3brgxoOeIy2OUA= + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== dependencies: call-bind "^1.0.0" define-properties "^1.1.3" @@ -6025,92 +6111,92 @@ object.assign@^4.1.0, object.assign@^4.1.1: object-keys "^1.1.1" object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: - version "2.1.1" - resolved "https://registry.npm.taobao.org/object.getownpropertydescriptors/download/object.getownpropertydescriptors-2.1.1.tgz?cache=0&sync_timestamp=1606459922634&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject.getownpropertydescriptors%2Fdownload%2Fobject.getownpropertydescriptors-2.1.1.tgz#0dfda8d108074d9c563e80490c883b6661091544" - integrity sha1-Df2o0QgHTZxWPoBJDIg7ZmEJFUQ= + version "2.1.2" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz#1bd63aeacf0d5d2d2f31b5e393b03a7c601a23f7" + integrity sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" + es-abstract "^1.18.0-next.2" object.pick@^1.3.0: version "1.3.0" - resolved "https://registry.npm.taobao.org/object.pick/download/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" object.values@^1.1.0: - version "1.1.2" - resolved "https://registry.npm.taobao.org/object.values/download/object.values-1.1.2.tgz#7a2015e06fcb0f546bd652486ce8583a4731c731" - integrity sha1-eiAV4G/LD1Rr1lJIbOhYOkcxxzE= + version "1.1.3" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.3.tgz#eaa8b1e17589f02f698db093f7c62ee1699742ee" + integrity sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" + es-abstract "^1.18.0-next.2" has "^1.0.3" obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" - resolved "https://registry.npm.taobao.org/obuf/download/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha1-Cb6jND1BhZ69RGKS0RydTbYZCE4= + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== on-finished@~2.3.0: version "2.3.0" - resolved "https://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= dependencies: ee-first "1.1.1" on-headers@~1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/on-headers/download/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha1-dysK5qqlJcOZ5Imt+tkMQD6zwo8= + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" - resolved "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" onetime@^2.0.0: version "2.0.1" - resolved "https://registry.npm.taobao.org/onetime/download/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= dependencies: mimic-fn "^1.0.0" onetime@^5.1.0: version "5.1.2" - resolved "https://registry.npm.taobao.org/onetime/download/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha1-0Oluu1awdHbfHdnEgG5SN5hcpF4= + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" open@^6.3.0: version "6.4.0" - resolved "https://registry.npm.taobao.org/open/download/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" - integrity sha1-XBPpbQ3IlGhhZPGJZez+iJ7PyKk= + resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" + integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg== dependencies: is-wsl "^1.1.0" opener@^1.5.1: version "1.5.2" - resolved "https://registry.npm.taobao.org/opener/download/opener-1.5.2.tgz?cache=0&sync_timestamp=1598732797840&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fopener%2Fdownload%2Fopener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" - integrity sha1-XTfh81B3udysQwE3InGv3rKhNZg= + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" + integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== opn@^5.5.0: version "5.5.0" - resolved "https://registry.npm.taobao.org/opn/download/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" - integrity sha1-/HFk+rVtI1kExRw7J9pnWMo7m/w= + resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" + integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== dependencies: is-wsl "^1.1.0" optionator@^0.8.3: version "0.8.3" - resolved "https://registry.npm.taobao.org/optionator/download/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha1-hPodA2/p08fiHZmIS2ARZ+yPtJU= + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.6" @@ -6121,8 +6207,8 @@ optionator@^0.8.3: ora@^3.4.0: version "3.4.0" - resolved "https://registry.npm.taobao.org/ora/download/ora-3.4.0.tgz?cache=0&sync_timestamp=1609228433875&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fora%2Fdownload%2Fora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" - integrity sha1-vwdSSRBZo+8+1MhQl1Md6f280xg= + resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" + integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg== dependencies: chalk "^2.4.2" cli-cursor "^2.1.0" @@ -6133,85 +6219,85 @@ ora@^3.4.0: original@^1.0.0: version "1.0.2" - resolved "https://registry.npm.taobao.org/original/download/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" - integrity sha1-5EKmHP/hxf0gpl8yYcJmY7MD8l8= + resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" + integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg== dependencies: url-parse "^1.4.3" os-browserify@^0.3.0: version "0.3.0" - resolved "https://registry.npm.taobao.org/os-browserify/download/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= os-tmpdir@~1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/os-tmpdir/download/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= p-finally@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-finally@^2.0.0: version "2.0.1" - resolved "https://registry.npm.taobao.org/p-finally/download/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" - integrity sha1-vW/KqcVZoJa2gIBvTWV7Pw8kBWE= + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" + integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.1, p-limit@^2.3.0: version "2.3.0" - resolved "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1606288806475&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE= + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-locate@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ= + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== dependencies: p-limit "^2.0.0" p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.npm.taobao.org/p-locate/download/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha1-o0KLtwiLOmApL2aRkni3wpetTwc= + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" p-map@^2.0.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/p-map/download/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" - integrity sha1-MQko/u+cnsxltosXaTAYpmXOoXU= + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== p-map@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/p-map/download/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" - integrity sha1-1wTZr4orpoTiYA2aIVmD1BQal50= + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== dependencies: aggregate-error "^3.0.0" p-retry@^3.0.1: version "3.0.1" - resolved "https://registry.npm.taobao.org/p-retry/download/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" - integrity sha1-MWtMiJPiyNwc+okfQGxLQivr8yg= + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" + integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== dependencies: retry "^0.12.0" p-try@^2.0.0: version "2.2.0" - resolved "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha1-yyhoVA4xPWHeWPr741zpAE1VQOY= + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== pako@~1.0.5: version "1.0.11" - resolved "https://registry.npm.taobao.org/pako/download/pako-1.0.11.tgz?cache=0&sync_timestamp=1605741987327&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpako%2Fdownload%2Fpako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha1-bJWZ00DVTf05RjgCUqNXBaa5kr8= + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== parallel-transform@^1.1.0: version "1.2.0" - resolved "https://registry.npm.taobao.org/parallel-transform/download/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" - integrity sha1-kEnKN9bLIYLDsdLHIL6U0UpYFPw= + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== dependencies: cyclist "^1.0.1" inherits "^2.0.3" @@ -6219,22 +6305,22 @@ parallel-transform@^1.1.0: param-case@2.1.x: version "2.1.1" - resolved "https://registry.npm.taobao.org/param-case/download/param-case-2.1.1.tgz?cache=0&sync_timestamp=1606867782594&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparam-case%2Fdownload%2Fparam-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= dependencies: no-case "^2.2.0" parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.npm.taobao.org/parent-module/download/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI= + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" parse-asn1@^5.0.0, parse-asn1@^5.1.5: version "5.1.6" - resolved "https://registry.npm.taobao.org/parse-asn1/download/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha1-OFCAo+wTy2KmLTlAnLPoiETNrtQ= + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== dependencies: asn1.js "^5.2.0" browserify-aes "^1.0.0" @@ -6244,16 +6330,16 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: parse-json@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/parse-json/download/parse-json-4.0.0.tgz?cache=0&sync_timestamp=1598129168845&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse-json%2Fdownload%2Fparse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= dependencies: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" parse-json@^5.0.0: - version "5.1.0" - resolved "https://registry.npm.taobao.org/parse-json/download/parse-json-5.1.0.tgz?cache=0&sync_timestamp=1598129168845&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse-json%2Fdownload%2Fparse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646" - integrity sha1-+WCIzfJKj6qa6poAny2dlCyZlkY= + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: "@babel/code-frame" "^7.0.0" error-ex "^1.3.1" @@ -6262,99 +6348,99 @@ parse-json@^5.0.0: parse5-htmlparser2-tree-adapter@^6.0.0: version "6.0.1" - resolved "https://registry.npm.taobao.org/parse5-htmlparser2-tree-adapter/download/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" - integrity sha1-LN+a2CMyEUA3DU2/XT6Sx8jdxuY= + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" + integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== dependencies: parse5 "^6.0.1" parse5@^5.1.1: version "5.1.1" - resolved "https://registry.npm.taobao.org/parse5/download/parse5-5.1.1.tgz?cache=0&sync_timestamp=1595850937464&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse5%2Fdownload%2Fparse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" - integrity sha1-9o5OW6GFKsLK3AD0VV//bCq7YXg= + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== parse5@^6.0.1: version "6.0.1" - resolved "https://registry.npm.taobao.org/parse5/download/parse5-6.0.1.tgz?cache=0&sync_timestamp=1595850937464&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse5%2Fdownload%2Fparse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha1-4aHAhcVps9wIMhGE8Zo5zCf3wws= + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" - resolved "https://registry.npm.taobao.org/parseurl/download/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ= + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== pascalcase@^0.1.1: version "0.1.1" - resolved "https://registry.npm.taobao.org/pascalcase/download/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-browserify@0.0.1: version "0.0.1" - resolved "https://registry.npm.taobao.org/path-browserify/download/path-browserify-0.0.1.tgz?cache=0&sync_timestamp=1583254548523&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-browserify%2Fdownload%2Fpath-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha1-5sTd1+06onxoogzE5Q4aTug7vEo= + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== path-dirname@^1.0.0: version "1.0.2" - resolved "https://registry.npm.taobao.org/path-dirname/download/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= path-exists@^2.0.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/path-exists/download/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= dependencies: pinkie-promise "^2.0.0" path-exists@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/path-exists/download/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/path-exists/download/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha1-UTvb4tO5XXdi6METfvoZXGxhtbM= + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-is-inside@^1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/path-is-inside/download/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" - resolved "https://registry.npm.taobao.org/path-key/download/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" - resolved "https://registry.npm.taobao.org/path-key/download/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha1-WB9q3mWMu6ZaDTOA3ndTKVBU83U= + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.6: version "1.0.6" - resolved "https://registry.npm.taobao.org/path-parse/download/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha1-1i27VnlAXXLEc37FhgDp3c8G0kw= + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== path-to-regexp@0.1.7: version "0.1.7" - resolved "https://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-to-regexp%2Fdownload%2Fpath-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= path-type@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/path-type/download/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha1-zvMdyOCho7sNEFwM2Xzzv0f0428= + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== dependencies: pify "^3.0.0" pbkdf2@^3.0.3: version "3.1.1" - resolved "https://registry.npm.taobao.org/pbkdf2/download/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" - integrity sha1-y4cksPramEWWhW0abrr9NYRlS5Q= + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" + integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -6364,66 +6450,66 @@ pbkdf2@^3.0.3: performance-now@^2.1.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1, picomatch@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== pify@^2.0.0: version "2.3.0" - resolved "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= pify@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= pify@^4.0.1: version "4.0.1" - resolved "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE= + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== pinkie-promise@^2.0.0: version "2.0.1" - resolved "https://registry.npm.taobao.org/pinkie-promise/download/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" - resolved "https://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= pkg-dir@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-1.0.0.tgz?cache=0&sync_timestamp=1602858997485&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpkg-dir%2Fdownload%2Fpkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= dependencies: find-up "^1.0.0" pkg-dir@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-3.0.0.tgz?cache=0&sync_timestamp=1602858997485&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpkg-dir%2Fdownload%2Fpkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM= + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== dependencies: find-up "^3.0.0" pkg-dir@^4.1.0: version "4.2.0" - resolved "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-4.2.0.tgz?cache=0&sync_timestamp=1602858997485&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpkg-dir%2Fdownload%2Fpkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha1-8JkTPfft5CLoHR2ESCcO6z5CYfM= + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" pnp-webpack-plugin@^1.6.4: version "1.6.4" - resolved "https://registry.npm.taobao.org/pnp-webpack-plugin/download/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" - integrity sha1-yXEaxNxIpoXauvyG+Lbdn434QUk= + resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" + integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg== dependencies: ts-pnp "^1.1.6" @@ -6439,8 +6525,8 @@ portal-vue@^2.1.7: portfinder@^1.0.26: version "1.0.28" - resolved "https://registry.npm.taobao.org/portfinder/download/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" - integrity sha1-Z8RiKFK9U3TdHdkA93n1NGL6x3g= + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" + integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== dependencies: async "^2.6.2" debug "^3.1.1" @@ -6448,13 +6534,13 @@ portfinder@^1.0.26: posix-character-classes@^0.1.0: version "0.1.1" - resolved "https://registry.npm.taobao.org/posix-character-classes/download/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= postcss-calc@^7.0.1: version "7.0.5" - resolved "https://registry.npm.taobao.org/postcss-calc/download/postcss-calc-7.0.5.tgz?cache=0&sync_timestamp=1609689216761&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-calc%2Fdownload%2Fpostcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e" - integrity sha1-+KbpnxLmGcLrwjz2xIb9wVhgkz4= + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e" + integrity sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg== dependencies: postcss "^7.0.27" postcss-selector-parser "^6.0.2" @@ -6462,8 +6548,8 @@ postcss-calc@^7.0.1: postcss-colormin@^4.0.3: version "4.0.3" - resolved "https://registry.npm.taobao.org/postcss-colormin/download/postcss-colormin-4.0.3.tgz?cache=0&sync_timestamp=1603212631209&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-colormin%2Fdownload%2Fpostcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" - integrity sha1-rgYLzpPteUrHEmTwgTLVUJVr04E= + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" + integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== dependencies: browserslist "^4.0.0" color "^3.0.0" @@ -6473,52 +6559,52 @@ postcss-colormin@^4.0.3: postcss-convert-values@^4.0.1: version "4.0.1" - resolved "https://registry.npm.taobao.org/postcss-convert-values/download/postcss-convert-values-4.0.1.tgz?cache=0&sync_timestamp=1603212678518&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-convert-values%2Fdownload%2Fpostcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha1-yjgT7U2g+BL51DcDWE5Enr4Ymn8= + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" + integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== dependencies: postcss "^7.0.0" postcss-value-parser "^3.0.0" postcss-discard-comments@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-discard-comments/download/postcss-discard-comments-4.0.2.tgz?cache=0&sync_timestamp=1603212674275&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-discard-comments%2Fdownload%2Fpostcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" - integrity sha1-H7q9LCRr/2qq15l7KwkY9NevQDM= + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" + integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== dependencies: postcss "^7.0.0" postcss-discard-duplicates@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-discard-duplicates/download/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" - integrity sha1-P+EzzTyCKC5VD8myORdqkge3hOs= + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" + integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== dependencies: postcss "^7.0.0" postcss-discard-empty@^4.0.1: version "4.0.1" - resolved "https://registry.npm.taobao.org/postcss-discard-empty/download/postcss-discard-empty-4.0.1.tgz?cache=0&sync_timestamp=1603214506702&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-discard-empty%2Fdownload%2Fpostcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" - integrity sha1-yMlR6fc+2UKAGUWERKAq2Qu592U= + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" + integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== dependencies: postcss "^7.0.0" postcss-discard-overridden@^4.0.1: version "4.0.1" - resolved "https://registry.npm.taobao.org/postcss-discard-overridden/download/postcss-discard-overridden-4.0.1.tgz?cache=0&sync_timestamp=1603214507029&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-discard-overridden%2Fdownload%2Fpostcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" - integrity sha1-ZSrvipZybwKfXj4AFG7npOdV/1c= + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" + integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== dependencies: postcss "^7.0.0" postcss-load-config@^2.0.0: version "2.1.2" - resolved "https://registry.npm.taobao.org/postcss-load-config/download/postcss-load-config-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-load-config%2Fdownload%2Fpostcss-load-config-2.1.2.tgz#c5ea504f2c4aef33c7359a34de3573772ad7502a" - integrity sha1-xepQTyxK7zPHNZo03jVzdyrXUCo= + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.2.tgz#c5ea504f2c4aef33c7359a34de3573772ad7502a" + integrity sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw== dependencies: cosmiconfig "^5.0.0" import-cwd "^2.0.0" postcss-loader@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/postcss-loader/download/postcss-loader-3.0.0.tgz?cache=0&sync_timestamp=1605790964077&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-loader%2Fdownload%2Fpostcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" - integrity sha1-a5eUPkfHLYRfqeA/Jzdz1OjdbC0= + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" + integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA== dependencies: loader-utils "^1.1.0" postcss "^7.0.0" @@ -6527,8 +6613,8 @@ postcss-loader@^3.0.0: postcss-merge-longhand@^4.0.11: version "4.0.11" - resolved "https://registry.npm.taobao.org/postcss-merge-longhand/download/postcss-merge-longhand-4.0.11.tgz?cache=0&sync_timestamp=1603214507431&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-merge-longhand%2Fdownload%2Fpostcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" - integrity sha1-YvSaE+Sg7gTnuY9CuxYGLKJUniQ= + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" + integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== dependencies: css-color-names "0.0.4" postcss "^7.0.0" @@ -6537,8 +6623,8 @@ postcss-merge-longhand@^4.0.11: postcss-merge-rules@^4.0.3: version "4.0.3" - resolved "https://registry.npm.taobao.org/postcss-merge-rules/download/postcss-merge-rules-4.0.3.tgz?cache=0&sync_timestamp=1603214507785&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-merge-rules%2Fdownload%2Fpostcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" - integrity sha1-NivqT/Wh+Y5AdacTxsslrv75plA= + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" + integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== dependencies: browserslist "^4.0.0" caniuse-api "^3.0.0" @@ -6549,16 +6635,16 @@ postcss-merge-rules@^4.0.3: postcss-minify-font-values@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-minify-font-values/download/postcss-minify-font-values-4.0.2.tgz?cache=0&sync_timestamp=1603212675125&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-minify-font-values%2Fdownload%2Fpostcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" - integrity sha1-zUw0TM5HQ0P6xdgiBqssvLiv1aY= + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" + integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== dependencies: postcss "^7.0.0" postcss-value-parser "^3.0.0" postcss-minify-gradients@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-minify-gradients/download/postcss-minify-gradients-4.0.2.tgz?cache=0&sync_timestamp=1603212675225&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-minify-gradients%2Fdownload%2Fpostcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" - integrity sha1-k7KcL/UJnFNe7NpWxKpuZlpmNHE= + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" + integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== dependencies: cssnano-util-get-arguments "^4.0.0" is-color-stop "^1.0.0" @@ -6567,8 +6653,8 @@ postcss-minify-gradients@^4.0.2: postcss-minify-params@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-minify-params/download/postcss-minify-params-4.0.2.tgz?cache=0&sync_timestamp=1603214506337&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-minify-params%2Fdownload%2Fpostcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" - integrity sha1-a5zvAwwR41Jh+V9hjJADbWgNuHQ= + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" + integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== dependencies: alphanum-sort "^1.0.0" browserslist "^4.0.0" @@ -6579,8 +6665,8 @@ postcss-minify-params@^4.0.2: postcss-minify-selectors@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-minify-selectors/download/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" - integrity sha1-4uXrQL/uUA0M2SQ1APX46kJi+9g= + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" + integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== dependencies: alphanum-sort "^1.0.0" has "^1.0.0" @@ -6589,63 +6675,90 @@ postcss-minify-selectors@^4.0.2: postcss-modules-extract-imports@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/postcss-modules-extract-imports/download/postcss-modules-extract-imports-2.0.0.tgz?cache=0&sync_timestamp=1602588177787&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-extract-imports%2Fdownload%2Fpostcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" - integrity sha1-gYcZoa4doyX5gyRGsBE27rSTzX4= + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== dependencies: postcss "^7.0.5" +postcss-modules-extract-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" + integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== + postcss-modules-local-by-default@^3.0.2: version "3.0.3" - resolved "https://registry.npm.taobao.org/postcss-modules-local-by-default/download/postcss-modules-local-by-default-3.0.3.tgz?cache=0&sync_timestamp=1602587565462&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-local-by-default%2Fdownload%2Fpostcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" - integrity sha1-uxTgzHgnnVBNvcv9fgyiiZP/u7A= + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" + integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== dependencies: icss-utils "^4.1.1" postcss "^7.0.32" postcss-selector-parser "^6.0.2" postcss-value-parser "^4.1.0" +postcss-modules-local-by-default@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" + integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + postcss-modules-scope@^2.2.0: version "2.2.0" - resolved "https://registry.npm.taobao.org/postcss-modules-scope/download/postcss-modules-scope-2.2.0.tgz?cache=0&sync_timestamp=1602593150083&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-scope%2Fdownload%2Fpostcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" - integrity sha1-OFyuATzHdD9afXYC0Qc6iequYu4= + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" + integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== dependencies: postcss "^7.0.6" postcss-selector-parser "^6.0.0" +postcss-modules-scope@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" + integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== + dependencies: + postcss-selector-parser "^6.0.4" + postcss-modules-values@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/postcss-modules-values/download/postcss-modules-values-3.0.0.tgz?cache=0&sync_timestamp=1602586198892&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-values%2Fdownload%2Fpostcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" - integrity sha1-W1AA1uuuKbQlUwG0o6VFdEI+fxA= + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== dependencies: icss-utils "^4.0.0" postcss "^7.0.6" -postcss-modules@^3.2.2: - version "3.2.2" - resolved "https://registry.npm.taobao.org/postcss-modules/download/postcss-modules-3.2.2.tgz?cache=0&sync_timestamp=1606641138659&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules%2Fdownload%2Fpostcss-modules-3.2.2.tgz#ee390de0f9f18e761e1778dfb9be26685c02c51f" - integrity sha1-7jkN4PnxjnYeF3jfub4maFwCxR8= +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-modules@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-4.0.0.tgz#2bc7f276ab88f3f1b0fadf6cbd7772d43b5f3b9b" + integrity sha512-ghS/ovDzDqARm4Zj6L2ntadjyQMoyJmi0JkLlYtH2QFLrvNlxH5OAVRPWPeKilB0pY7SbuhO173KOWkPAxRJcw== dependencies: generic-names "^2.0.1" icss-replace-symbols "^1.1.0" lodash.camelcase "^4.3.0" - postcss "^7.0.32" - postcss-modules-extract-imports "^2.0.0" - postcss-modules-local-by-default "^3.0.2" - postcss-modules-scope "^2.2.0" - postcss-modules-values "^3.0.0" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" string-hash "^1.1.1" postcss-normalize-charset@^4.0.1: version "4.0.1" - resolved "https://registry.npm.taobao.org/postcss-normalize-charset/download/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" - integrity sha1-izWt067oOhNrBHHg1ZvlilAoXdQ= + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" + integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== dependencies: postcss "^7.0.0" postcss-normalize-display-values@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-normalize-display-values/download/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" - integrity sha1-Db4EpM6QY9RmftK+R2u4MMglk1o= + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" + integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== dependencies: cssnano-util-get-match "^4.0.0" postcss "^7.0.0" @@ -6653,8 +6766,8 @@ postcss-normalize-display-values@^4.0.2: postcss-normalize-positions@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-normalize-positions/download/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" - integrity sha1-BfdX+E8mBDc3g2ipH4ky1LECkX8= + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" + integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== dependencies: cssnano-util-get-arguments "^4.0.0" has "^1.0.0" @@ -6663,8 +6776,8 @@ postcss-normalize-positions@^4.0.2: postcss-normalize-repeat-style@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-normalize-repeat-style/download/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" - integrity sha1-xOu8KJ85kaAo1EdRy90RkYsXkQw= + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" + integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== dependencies: cssnano-util-get-arguments "^4.0.0" cssnano-util-get-match "^4.0.0" @@ -6673,8 +6786,8 @@ postcss-normalize-repeat-style@^4.0.2: postcss-normalize-string@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-normalize-string/download/postcss-normalize-string-4.0.2.tgz?cache=0&sync_timestamp=1603212828249&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-normalize-string%2Fdownload%2Fpostcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" - integrity sha1-zUTECrB6DHo23F6Zqs4eyk7CaQw= + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" + integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== dependencies: has "^1.0.0" postcss "^7.0.0" @@ -6682,8 +6795,8 @@ postcss-normalize-string@^4.0.2: postcss-normalize-timing-functions@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-normalize-timing-functions/download/postcss-normalize-timing-functions-4.0.2.tgz?cache=0&sync_timestamp=1603212828352&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-normalize-timing-functions%2Fdownload%2Fpostcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" - integrity sha1-jgCcoqOUnNr4rSPmtquZy159KNk= + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" + integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== dependencies: cssnano-util-get-match "^4.0.0" postcss "^7.0.0" @@ -6691,8 +6804,8 @@ postcss-normalize-timing-functions@^4.0.2: postcss-normalize-unicode@^4.0.1: version "4.0.1" - resolved "https://registry.npm.taobao.org/postcss-normalize-unicode/download/postcss-normalize-unicode-4.0.1.tgz?cache=0&sync_timestamp=1603212933097&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-normalize-unicode%2Fdownload%2Fpostcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" - integrity sha1-hBvUj9zzAZrUuqdJOj02O1KuHPs= + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" + integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== dependencies: browserslist "^4.0.0" postcss "^7.0.0" @@ -6700,8 +6813,8 @@ postcss-normalize-unicode@^4.0.1: postcss-normalize-url@^4.0.1: version "4.0.1" - resolved "https://registry.npm.taobao.org/postcss-normalize-url/download/postcss-normalize-url-4.0.1.tgz?cache=0&sync_timestamp=1603212828548&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-normalize-url%2Fdownload%2Fpostcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" - integrity sha1-EOQ3+GvHx+WPe5ZS7YeNqqlfquE= + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" + integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== dependencies: is-absolute-url "^2.0.0" normalize-url "^3.0.0" @@ -6710,16 +6823,16 @@ postcss-normalize-url@^4.0.1: postcss-normalize-whitespace@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-normalize-whitespace/download/postcss-normalize-whitespace-4.0.2.tgz?cache=0&sync_timestamp=1603212828669&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-normalize-whitespace%2Fdownload%2Fpostcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" - integrity sha1-vx1AcP5Pzqh9E0joJdjMDF+qfYI= + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" + integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== dependencies: postcss "^7.0.0" postcss-value-parser "^3.0.0" postcss-ordered-values@^4.1.2: version "4.1.2" - resolved "https://registry.npm.taobao.org/postcss-ordered-values/download/postcss-ordered-values-4.1.2.tgz?cache=0&sync_timestamp=1603212828777&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-ordered-values%2Fdownload%2Fpostcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" - integrity sha1-DPdcgg7H1cTSgBiVWeC1ceusDu4= + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" + integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== dependencies: cssnano-util-get-arguments "^4.0.0" postcss "^7.0.0" @@ -6727,8 +6840,8 @@ postcss-ordered-values@^4.1.2: postcss-reduce-initial@^4.0.3: version "4.0.3" - resolved "https://registry.npm.taobao.org/postcss-reduce-initial/download/postcss-reduce-initial-4.0.3.tgz?cache=0&sync_timestamp=1603214658414&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-reduce-initial%2Fdownload%2Fpostcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" - integrity sha1-f9QuvqXpyBRgljniwuhK4nC6SN8= + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" + integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== dependencies: browserslist "^4.0.0" caniuse-api "^3.0.0" @@ -6737,8 +6850,8 @@ postcss-reduce-initial@^4.0.3: postcss-reduce-transforms@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-reduce-transforms/download/postcss-reduce-transforms-4.0.2.tgz?cache=0&sync_timestamp=1603214658798&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-reduce-transforms%2Fdownload%2Fpostcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" - integrity sha1-F++kBerMbge+NBSlyi0QdGgdTik= + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" + integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== dependencies: cssnano-util-get-match "^4.0.0" has "^1.0.0" @@ -6747,8 +6860,8 @@ postcss-reduce-transforms@^4.0.2: postcss-selector-parser@^3.0.0: version "3.1.2" - resolved "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-3.1.2.tgz?cache=0&sync_timestamp=1601045461414&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" - integrity sha1-sxD1xMD9r3b5SQK7qjDbaqhPUnA= + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" + integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA== dependencies: dot-prop "^5.2.0" indexes-of "^1.0.1" @@ -6756,8 +6869,8 @@ postcss-selector-parser@^3.0.0: postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: version "6.0.4" - resolved "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-6.0.4.tgz?cache=0&sync_timestamp=1601045461414&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" - integrity sha1-VgdaE4CgRgTDiwY+p3Z6Epr1wrM= + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" + integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw== dependencies: cssesc "^3.0.0" indexes-of "^1.0.1" @@ -6766,8 +6879,8 @@ postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector postcss-svgo@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/postcss-svgo/download/postcss-svgo-4.0.2.tgz?cache=0&sync_timestamp=1603214658950&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-svgo%2Fdownload%2Fpostcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" - integrity sha1-F7mXvHEbMzurFDqu07jT1uPTglg= + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" + integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== dependencies: is-svg "^3.0.0" postcss "^7.0.0" @@ -6776,8 +6889,8 @@ postcss-svgo@^4.0.2: postcss-unique-selectors@^4.0.1: version "4.0.1" - resolved "https://registry.npm.taobao.org/postcss-unique-selectors/download/postcss-unique-selectors-4.0.1.tgz?cache=0&sync_timestamp=1603214659417&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-unique-selectors%2Fdownload%2Fpostcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" - integrity sha1-lEaRHzKJv9ZMbWgPBzwDsfnuS6w= + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" + integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== dependencies: alphanum-sort "^1.0.0" postcss "^7.0.0" @@ -6785,98 +6898,107 @@ postcss-unique-selectors@^4.0.1: postcss-value-parser@^3.0.0: version "3.3.1" - resolved "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha1-n/giVH4okyE88cMO+lGsX9G6goE= + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: version "4.1.0" - resolved "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" - integrity sha1-RD9qIM7WSBor2k+oUypuVdeJoss= + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" + integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: version "7.0.35" - resolved "https://registry.npm.taobao.org/postcss/download/postcss-7.0.35.tgz?cache=0&sync_timestamp=1610019519217&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss%2Fdownload%2Fpostcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" - integrity sha1-0r4AuZj38hHYonaXQHny6SuXDiQ= + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" + integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== dependencies: chalk "^2.4.2" source-map "^0.6.1" supports-color "^6.1.0" +postcss@^8.1.10: + version "8.2.8" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.8.tgz#0b90f9382efda424c4f0f69a2ead6f6830d08ece" + integrity sha512-1F0Xb2T21xET7oQV9eKuctbM9S7BC0fetoHCc4H13z0PT6haiRLP4T0ZY4XWh7iLP0usgqykT6p9B2RtOf4FPw== + dependencies: + colorette "^1.2.2" + nanoid "^3.1.20" + source-map "^0.6.1" + prelude-ls@~1.1.2: version "1.1.2" - resolved "https://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= prepend-http@^1.0.0: version "1.0.4" - resolved "https://registry.npm.taobao.org/prepend-http/download/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= prettier@^1.18.2: version "1.19.1" - resolved "https://registry.npm.taobao.org/prettier/download/prettier-1.19.1.tgz?cache=0&sync_timestamp=1606521150228&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fprettier%2Fdownload%2Fprettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" - integrity sha1-99f1/4qc2HKnvkyhQglZVqYHl8s= + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== pretty-bytes@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.5.0.tgz#0cecda50a74a941589498011cf23275aa82b339e" - integrity sha512-p+T744ZyjjiaFlMUZZv6YPC5JrkNj8maRmPaQCWFJFplUAzpIUTRaTcS+7wmZtUoFXHtESJb23ISliaWyz3SHA== + version "5.6.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" + integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== pretty-error@^2.0.2: version "2.1.2" - resolved "https://registry.npm.taobao.org/pretty-error/download/pretty-error-2.1.2.tgz?cache=0&sync_timestamp=1609589327290&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpretty-error%2Fdownload%2Fpretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6" - integrity sha1-von4LYGxyG7I/fvDhQRYgnJ/k7Y= + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6" + integrity sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw== dependencies: lodash "^4.17.20" renderkid "^2.0.4" process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha1-eCDZsWEgzFXKmud5JoCufbptf+I= + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== process@^0.11.10: version "0.11.10" - resolved "https://registry.npm.taobao.org/process/download/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= progress@^2.0.0: version "2.0.3" - resolved "https://registry.npm.taobao.org/progress/download/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha1-foz42PW48jnBvGi+tOt4Vn1XLvg= + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== promise-inflight@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/promise-inflight/download/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= proxy-addr@~2.0.5: version "2.0.6" - resolved "https://registry.npm.taobao.org/proxy-addr/download/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" - integrity sha1-/cIzZQVEfT8vLGOO0nLK9hS7sr8= + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" + integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== dependencies: forwarded "~0.1.2" ipaddr.js "1.9.1" prr@~1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/prr/download/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= pseudomap@^1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/pseudomap/download/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.28: version "1.8.0" - resolved "https://registry.npm.taobao.org/psl/download/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha1-kyb4vPsBOtzABf3/BWrM4CDlHCQ= + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== public-encrypt@^4.0.0: version "4.0.3" - resolved "https://registry.npm.taobao.org/public-encrypt/download/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA= + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" browserify-rsa "^4.0.0" @@ -6887,24 +7009,24 @@ public-encrypt@^4.0.0: pump@^2.0.0: version "2.0.1" - resolved "https://registry.npm.taobao.org/pump/download/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk= + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== dependencies: end-of-stream "^1.1.0" once "^1.3.1" pump@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/pump/download/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ= + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== dependencies: end-of-stream "^1.1.0" once "^1.3.1" pumpify@^1.3.3: version "1.5.1" - resolved "https://registry.npm.taobao.org/pumpify/download/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - integrity sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4= + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== dependencies: duplexify "^3.6.0" inherits "^2.0.3" @@ -6912,37 +7034,37 @@ pumpify@^1.3.3: punycode@1.3.2: version "1.3.2" - resolved "https://registry.npm.taobao.org/punycode/download/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= punycode@^1.2.4: version "1.4.1" - resolved "https://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" - resolved "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha1-tYsBCsQMIsVldhbI0sLALHv0eew= + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== q@^1.1.2: version "1.5.1" - resolved "https://registry.npm.taobao.org/q/download/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= qs@6.7.0: version "6.7.0" - resolved "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz?cache=0&sync_timestamp=1598867238193&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fqs%2Fdownload%2Fqs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha1-QdwaAV49WB8WIXdr4xr7KHapsbw= + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== qs@~6.5.2: version "6.5.2" - resolved "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz?cache=0&sync_timestamp=1598867238193&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fqs%2Fdownload%2Fqs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha1-yzroBuh0BERYTvFUzo7pjUA/PjY= + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== query-string@^4.1.0: version "4.3.4" - resolved "https://registry.npm.taobao.org/query-string/download/query-string-4.3.4.tgz?cache=0&sync_timestamp=1609310798081&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fquery-string%2Fdownload%2Fquery-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= dependencies: object-assign "^4.1.0" @@ -6950,43 +7072,43 @@ query-string@^4.1.0: querystring-es3@^0.2.0: version "0.2.1" - resolved "https://registry.npm.taobao.org/querystring-es3/download/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= querystring@0.2.0: version "0.2.0" - resolved "https://registry.npm.taobao.org/querystring/download/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= querystringify@^2.1.1: version "2.2.0" - resolved "https://registry.npm.taobao.org/querystringify/download/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" - integrity sha1-M0WUG0FTy50ILY7uTNogFqmu9/Y= + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/randombytes/download/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo= + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" - resolved "https://registry.npm.taobao.org/randomfill/download/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha1-ySGW/IarQr6YPxvzF3giSTHWFFg= + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" - resolved "https://registry.npm.taobao.org/range-parser/download/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE= + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== raw-body@2.4.0: version "2.4.0" - resolved "https://registry.npm.taobao.org/raw-body/download/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha1-oc5vucm8NWylLoklarWQWeE9AzI= + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== dependencies: bytes "3.1.0" http-errors "1.7.2" @@ -6995,8 +7117,8 @@ raw-body@2.4.0: read-pkg@^5.1.1: version "5.2.0" - resolved "https://registry.npm.taobao.org/read-pkg/download/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" - integrity sha1-e/KVQ4yloz5WzTDgU7NO5yUMk8w= + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== dependencies: "@types/normalize-package-data" "^2.4.0" normalize-package-data "^2.5.0" @@ -7005,8 +7127,8 @@ read-pkg@^5.1.1: "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" - resolved "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c= + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -7018,8 +7140,8 @@ read-pkg@^5.1.1: readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0: version "3.6.0" - resolved "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha1-M3u9o63AcGvT4CRCaihtS0sskZg= + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -7027,8 +7149,8 @@ readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0: readdirp@^2.2.1: version "2.2.1" - resolved "https://registry.npm.taobao.org/readdirp/download/readdirp-2.2.1.tgz?cache=0&sync_timestamp=1602584469356&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha1-DodiKjMlqjPokihcr4tOhGUppSU= + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" micromatch "^3.1.10" @@ -7036,65 +7158,65 @@ readdirp@^2.2.1: readdirp@~3.5.0: version "3.5.0" - resolved "https://registry.npm.taobao.org/readdirp/download/readdirp-3.5.0.tgz?cache=0&sync_timestamp=1602584469356&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" - integrity sha1-m6dMAZsV02UnjS6Ru4xI17TULJ4= + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== dependencies: picomatch "^2.2.1" regenerate-unicode-properties@^8.2.0: version "8.2.0" - resolved "https://registry.npm.taobao.org/regenerate-unicode-properties/download/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" - integrity sha1-5d5xEdZV57pgwFfb6f83yH5lzew= + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== dependencies: regenerate "^1.4.0" regenerate@^1.4.0: version "1.4.2" - resolved "https://registry.npm.taobao.org/regenerate/download/regenerate-1.4.2.tgz?cache=0&sync_timestamp=1604218535967&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerate%2Fdownload%2Fregenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha1-uTRtiCfo9aMve6KWN9OYtpAUhIo= + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.11.0: version "0.11.1" - resolved "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk= + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-runtime@^0.13.4: version "0.13.7" - resolved "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" - integrity sha1-ysLazIoepnX+qrrriugziYrkb1U= + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== regenerator-transform@^0.14.2: version "0.14.5" - resolved "https://registry.npm.taobao.org/regenerator-transform/download/regenerator-transform-0.14.5.tgz?cache=0&sync_timestamp=1593557458064&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-transform%2Fdownload%2Fregenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" - integrity sha1-yY2hVGg2ccnE3LFuznNlF+G3/rQ= + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== dependencies: "@babel/runtime" "^7.8.4" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/regex-not/download/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw= + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" regexp.prototype.flags@^1.2.0: - version "1.3.0" - resolved "https://registry.npm.taobao.org/regexp.prototype.flags/download/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" - integrity sha1-erqJs8E6ZFCdq888qNn7ub31y3U= + version "1.3.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" + integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== dependencies: + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" regexpp@^2.0.1: version "2.0.1" - resolved "https://registry.npm.taobao.org/regexpp/download/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha1-jRnTHPYySCtYkEn4KB+T28uk0H8= + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== regexpu-core@^4.7.1: version "4.7.1" - resolved "https://registry.npm.taobao.org/regexpu-core/download/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" - integrity sha1-LepamgcjMpj78NuR+pq8TG4PitY= + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== dependencies: regenerate "^1.4.0" regenerate-unicode-properties "^8.2.0" @@ -7103,37 +7225,32 @@ regexpu-core@^4.7.1: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.2.0" -register-service-worker@^1.7.1: - version "1.7.2" - resolved "https://registry.npm.taobao.org/register-service-worker/download/register-service-worker-1.7.2.tgz?cache=0&sync_timestamp=1607600671701&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregister-service-worker%2Fdownload%2Fregister-service-worker-1.7.2.tgz#6516983e1ef790a98c4225af1216bc80941a4bd2" - integrity sha1-ZRaYPh73kKmMQiWvEha8gJQaS9I= - regjsgen@^0.5.1: version "0.5.2" - resolved "https://registry.npm.taobao.org/regjsgen/download/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" - integrity sha1-kv8pX7He7L9uzaslQ9IH6RqjNzM= + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" + integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== regjsparser@^0.6.4: - version "0.6.4" - resolved "https://registry.npm.taobao.org/regjsparser/download/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" - integrity sha1-p2n4aEMIQBpm6bUp0kNv9NBmYnI= + version "0.6.7" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.7.tgz#c00164e1e6713c2e3ee641f1701c4b7aa0a7f86c" + integrity sha512-ib77G0uxsA2ovgiYbCVGx4Pv3PSttAx2vIwidqQzbL2U5S4Q+j00HdSAneSBuyVcMvEnTXMjiGgB+DlXozVhpQ== dependencies: jsesc "~0.5.0" relateurl@0.2.x: version "0.2.7" - resolved "https://registry.npm.taobao.org/relateurl/download/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= remove-trailing-separator@^1.0.1: version "1.1.0" - resolved "https://registry.npm.taobao.org/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= renderkid@^2.0.4: version "2.0.5" - resolved "https://registry.npm.taobao.org/renderkid/download/renderkid-2.0.5.tgz?cache=0&sync_timestamp=1609588540446&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frenderkid%2Fdownload%2Frenderkid-2.0.5.tgz#483b1ac59c6601ab30a7a596a5965cabccfdd0a5" - integrity sha1-SDsaxZxmAaswp6WWpZZcq8z90KU= + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.5.tgz#483b1ac59c6601ab30a7a596a5965cabccfdd0a5" + integrity sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ== dependencies: css-select "^2.0.2" dom-converter "^0.2" @@ -7143,18 +7260,18 @@ renderkid@^2.0.4: repeat-element@^1.1.2: version "1.1.3" - resolved "https://registry.npm.taobao.org/repeat-element/download/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4= + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== repeat-string@^1.6.1: version "1.6.1" - resolved "https://registry.npm.taobao.org/repeat-string/download/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= request@^2.88.2: version "2.88.2" - resolved "https://registry.npm.taobao.org/request/download/request-2.88.2.tgz?cache=0&sync_timestamp=1598867240781&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frequest%2Fdownload%2Frequest-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM= + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -7179,52 +7296,52 @@ request@^2.88.2: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.npm.taobao.org/require-directory/download/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-main-filename@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/require-main-filename/download/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs= + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== requires-port@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/requires-port/download/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= resolve-cwd@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/resolve-cwd/download/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= dependencies: resolve-from "^3.0.0" resolve-from@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/resolve-from/download/resolve-from-3.0.0.tgz?cache=0&sync_timestamp=1598869140250&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve-from%2Fdownload%2Fresolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" integrity sha1-six699nWiBvItuZTM17rywoYh0g= resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/resolve-from/download/resolve-from-4.0.0.tgz?cache=0&sync_timestamp=1598869140250&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve-from%2Fdownload%2Fresolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY= + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-url@^0.2.1: version "0.2.1" - resolved "https://registry.npm.taobao.org/resolve-url/download/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2: - version "1.19.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" - integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== dependencies: - is-core-module "^2.1.0" + is-core-module "^2.2.0" path-parse "^1.0.6" restore-cursor@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/restore-cursor/download/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= dependencies: onetime "^2.0.0" @@ -7232,50 +7349,50 @@ restore-cursor@^2.0.0: restore-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.npm.taobao.org/restore-cursor/download/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha1-OfZ8VLOnpYzqUjbZXPADQjljH34= + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== dependencies: onetime "^5.1.0" signal-exit "^3.0.2" ret@~0.1.10: version "0.1.15" - resolved "https://registry.npm.taobao.org/ret/download/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w= + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== retry@^0.12.0: version "0.12.0" - resolved "https://registry.npm.taobao.org/retry/download/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= rgb-regex@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/rgb-regex/download/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= rgba-regex@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/rgba-regex/download/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= rimraf@2.6.3: version "2.6.3" - resolved "https://registry.npm.taobao.org/rimraf/download/rimraf-2.6.3.tgz?cache=0&sync_timestamp=1598867244181&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frimraf%2Fdownload%2Frimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha1-stEE/g2Psnz54KHNqCYt04M8bKs= + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3, rimraf@^2.7.1: version "2.7.1" - resolved "https://registry.npm.taobao.org/rimraf/download/rimraf-2.7.1.tgz?cache=0&sync_timestamp=1598867244181&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frimraf%2Fdownload%2Frimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha1-NXl/E6f9rcVmFCwp1PB8ytSD4+w= + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" - resolved "https://registry.npm.taobao.org/ripemd160/download/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw= + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -7317,54 +7434,54 @@ rollup@^1.31.1: run-async@^2.4.0: version "2.4.1" - resolved "https://registry.npm.taobao.org/run-async/download/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha1-hEDsz5nqPnC9QJ1JqriOEMGJpFU= + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" - resolved "https://registry.npm.taobao.org/run-queue/download/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= dependencies: aproba "^1.1.1" rxjs@^6.6.0: - version "6.6.3" - resolved "https://registry.npm.taobao.org/rxjs/download/rxjs-6.6.3.tgz?cache=0&sync_timestamp=1607308039044&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frxjs%2Fdownload%2Frxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" - integrity sha1-jKhGNcTaqQDA05Z6buesYCce5VI= + version "6.6.6" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.6.tgz#14d8417aa5a07c5e633995b525e1e3c0dec03b70" + integrity sha512-/oTwee4N4iWzAMAL9xdGKjkEHmIwupR3oXbQjCKywF1BeFohswF3vZdogbmEF6pZkOsXTzWkrZszrWpQTByYVg== dependencies: tslib "^1.9.0" safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha1-mR7GnSluAxN0fVm9/St0XDX4go0= + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" - resolved "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY= + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-regex@^1.1.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/safe-regex/download/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" - resolved "https://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo= + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@~1.2.4: version "1.2.4" - resolved "https://registry.npm.taobao.org/sax/download/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha1-KBYjTiN4vdxOU1T6tcqold9xANk= + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== schema-utils@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz?cache=0&sync_timestamp=1601922224938&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A= + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== dependencies: ajv "^6.1.0" ajv-errors "^1.0.0" @@ -7372,8 +7489,8 @@ schema-utils@^1.0.0: schema-utils@^2.0.0, schema-utils@^2.5.0, schema-utils@^2.6.5, schema-utils@^2.6.6, schema-utils@^2.7.0: version "2.7.1" - resolved "https://registry.npm.taobao.org/schema-utils/download/schema-utils-2.7.1.tgz?cache=0&sync_timestamp=1601922224938&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fschema-utils%2Fdownload%2Fschema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" - integrity sha1-HKTzLRskxZDCA7jnpQvw6kzTlNc= + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== dependencies: "@types/json-schema" "^7.0.5" ajv "^6.12.4" @@ -7381,42 +7498,42 @@ schema-utils@^2.0.0, schema-utils@^2.5.0, schema-utils@^2.6.5, schema-utils@^2.6 select-hose@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/select-hose/download/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= selfsigned@^1.10.8: version "1.10.8" - resolved "https://registry.npm.taobao.org/selfsigned/download/selfsigned-1.10.8.tgz?cache=0&sync_timestamp=1600186146412&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fselfsigned%2Fdownload%2Fselfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30" - integrity sha1-DRcgi30Swz+OrIXEGDXyf8PYGjA= + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30" + integrity sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w== dependencies: node-forge "^0.10.0" -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0: version "5.7.1" - resolved "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1606851857382&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha1-qVT5Ma66UI0we78Gnv8MAclhFvc= + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== semver@7.0.0: version "7.0.0" - resolved "https://registry.npm.taobao.org/semver/download/semver-7.0.0.tgz?cache=0&sync_timestamp=1606851857382&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha1-XzyjV2HkfgWyBsba/yz4FPAxa44= + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: version "6.3.0" - resolved "https://registry.npm.taobao.org/semver/download/semver-6.3.0.tgz?cache=0&sync_timestamp=1606851857382&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0= + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== semver@^7.3.2: version "7.3.4" - resolved "https://registry.npm.taobao.org/semver/download/semver-7.3.4.tgz?cache=0&sync_timestamp=1606851857382&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" - integrity sha1-J6qn0uTKdkUvmNOt0JOnLJQ+3Jc= + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== dependencies: lru-cache "^6.0.0" send@0.17.1: version "0.17.1" - resolved "https://registry.npm.taobao.org/send/download/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha1-wdiwWfeQD3Rm3Uk4vcROEd2zdsg= + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== dependencies: debug "2.6.9" depd "~1.1.2" @@ -7434,14 +7551,14 @@ send@0.17.1: serialize-javascript@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-4.0.0.tgz?cache=0&sync_timestamp=1599742605902&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fserialize-javascript%2Fdownload%2Fserialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" - integrity sha1-tSXhI4SJpez8Qq+sw/6Z5mb0sao= + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== dependencies: randombytes "^2.1.0" serve-index@^1.9.1: version "1.9.1" - resolved "https://registry.npm.taobao.org/serve-index/download/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= dependencies: accepts "~1.3.4" @@ -7454,8 +7571,8 @@ serve-index@^1.9.1: serve-static@1.14.1: version "1.14.1" - resolved "https://registry.npm.taobao.org/serve-static/download/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha1-Zm5jbcTwEPfvKZcKiKZ0MgiYsvk= + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" @@ -7464,13 +7581,13 @@ serve-static@1.14.1: set-blocking@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" - resolved "https://registry.npm.taobao.org/set-value/download/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha1-oY1AUw5vB95CKMfe/kInr4ytAFs= + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -7479,82 +7596,82 @@ set-value@^2.0.0, set-value@^2.0.1: setimmediate@^1.0.4: version "1.0.5" - resolved "https://registry.npm.taobao.org/setimmediate/download/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= setprototypeof@1.1.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY= + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== setprototypeof@1.1.1: version "1.1.1" - resolved "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM= + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" - resolved "https://registry.npm.taobao.org/sha.js/download/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc= + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" shebang-command@^1.2.0: version "1.2.0" - resolved "https://registry.npm.taobao.org/shebang-command/download/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/shebang-command/download/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha1-zNCvT4g1+9wmW4JGGq8MNmY/NOo= + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/shebang-regex/download/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/shebang-regex/download/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha1-rhbxZE2HPsrYQ7AwexQzYtTEIXI= + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.6.1: version "1.7.2" - resolved "https://registry.npm.taobao.org/shell-quote/download/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" - integrity sha1-Z6fQLHbJ2iT5nSCAj8re0ODgS+I= + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" + integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" - resolved "https://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha1-oUEMLt2PB3sItOJTyOrPyvBXRhw= + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== simple-swizzle@^0.2.2: version "0.2.2" - resolved "https://registry.npm.taobao.org/simple-swizzle/download/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= dependencies: is-arrayish "^0.3.1" slash@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/slash/download/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= slash@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/slash/download/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha1-3lUoUaF1nfOo8gZTVEL17E3eq0Q= + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== slice-ansi@^2.1.0: version "2.1.0" - resolved "https://registry.npm.taobao.org/slice-ansi/download/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha1-ys12k0YaY3pXiNkqfdT7oGjoFjY= + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== dependencies: ansi-styles "^3.2.0" astral-regex "^1.0.0" @@ -7562,8 +7679,8 @@ slice-ansi@^2.1.0: snapdragon-node@^2.0.1: version "2.1.1" - resolved "https://registry.npm.taobao.org/snapdragon-node/download/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha1-bBdfhv8UvbByRWPo88GwIaKGhTs= + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" isobject "^3.0.0" @@ -7571,15 +7688,15 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" - resolved "https://registry.npm.taobao.org/snapdragon-util/download/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI= + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" - resolved "https://registry.npm.taobao.org/snapdragon/download/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0= + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" debug "^2.2.0" @@ -7592,8 +7709,8 @@ snapdragon@^0.8.1: sockjs-client@^1.5.0: version "1.5.0" - resolved "https://registry.npm.taobao.org/sockjs-client/download/sockjs-client-1.5.0.tgz#2f8ff5d4b659e0d092f7aba0b7c386bd2aa20add" - integrity sha1-L4/11LZZ4NCS96ugt8OGvSqiCt0= + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.0.tgz#2f8ff5d4b659e0d092f7aba0b7c386bd2aa20add" + integrity sha512-8Dt3BDi4FYNrCFGTL/HtwVzkARrENdwOUf1ZoW/9p3M8lZdFT35jVdrHza+qgxuG9H3/shR4cuX/X9umUrjP8Q== dependencies: debug "^3.2.6" eventsource "^1.0.7" @@ -7604,8 +7721,8 @@ sockjs-client@^1.5.0: sockjs@^0.3.21: version "0.3.21" - resolved "https://registry.npm.taobao.org/sockjs/download/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" - integrity sha1-s0/7mOeWkwtgoM+hGQTWozmn1Bc= + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" + integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== dependencies: faye-websocket "^0.11.3" uuid "^3.4.0" @@ -7613,20 +7730,20 @@ sockjs@^0.3.21: sort-keys@^1.0.0: version "1.1.2" - resolved "https://registry.npm.taobao.org/sort-keys/download/sort-keys-1.1.2.tgz?cache=0&sync_timestamp=1609311347731&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsort-keys%2Fdownload%2Fsort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= dependencies: is-plain-obj "^1.0.0" source-list-map@^2.0.0: version "2.0.1" - resolved "https://registry.npm.taobao.org/source-list-map/download/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ= + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== source-map-resolve@^0.5.0: version "0.5.3" - resolved "https://registry.npm.taobao.org/source-map-resolve/download/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha1-GQhmvs51U+H48mei7oLGBrVQmho= + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: atob "^2.1.2" decode-uri-component "^0.2.0" @@ -7636,67 +7753,67 @@ source-map-resolve@^0.5.0: source-map-support@~0.5.12: version "0.5.19" - resolved "https://registry.npm.taobao.org/source-map-support/download/source-map-support-0.5.19.tgz?cache=0&sync_timestamp=1598869144200&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map-support%2Fdownload%2Fsource-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha1-qYti+G3K9PZzmWSMCFKRq56P7WE= + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.npm.taobao.org/source-map-url/download/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" - resolved "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" - resolved "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha1-dHIq8y6WFOnCh6jQu95IteLxomM= + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@^0.7.3: version "0.7.3" - resolved "https://registry.npm.taobao.org/source-map/download/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha1-UwL4FpAxc1ImVECS5kmB91F1A4M= + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== sourcemap-codec@^1.4.4: version "1.4.8" - resolved "https://registry.npm.taobao.org/sourcemap-codec/download/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha1-6oBL2UhXQC5pktBaOO8a41qatMQ= + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== spdx-correct@^3.0.0: version "3.1.1" - resolved "https://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha1-3s6BrJweZxPl99G28X1Gj6U9iak= + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: version "2.3.0" - resolved "https://registry.npm.taobao.org/spdx-exceptions/download/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha1-PyjOGnegA3JoPq3kpDMYNSeiFj0= + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== spdx-expression-parse@^3.0.0: version "3.0.1" - resolved "https://registry.npm.taobao.org/spdx-expression-parse/download/spdx-expression-parse-3.0.1.tgz?cache=0&sync_timestamp=1598867270278&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fspdx-expression-parse%2Fdownload%2Fspdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha1-z3D1BILu/cmOPOCmgz5KU87rpnk= + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: version "3.0.7" - resolved "https://registry.npm.taobao.org/spdx-license-ids/download/spdx-license-ids-3.0.7.tgz?cache=0&sync_timestamp=1606610954359&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fspdx-license-ids%2Fdownload%2Fspdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65" - integrity sha1-6cGKQQ5e1+EkQqVJ+9ivp2cDjWU= + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65" + integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ== spdy-transport@^3.0.0: version "3.0.0" - resolved "https://registry.npm.taobao.org/spdy-transport/download/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" - integrity sha1-ANSGOmQArXXfkzYaFghgXl3NzzE= + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== dependencies: debug "^4.1.0" detect-node "^2.0.4" @@ -7707,8 +7824,8 @@ spdy-transport@^3.0.0: spdy@^4.0.2: version "4.0.2" - resolved "https://registry.npm.taobao.org/spdy/download/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" - integrity sha1-t09GYgOj7aRSwCSSuR+56EonZ3s= + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== dependencies: debug "^4.1.0" handle-thing "^2.0.0" @@ -7718,20 +7835,20 @@ spdy@^4.0.2: split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" - resolved "https://registry.npm.taobao.org/split-string/download/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha1-fLCd2jqGWFcFxks5pkZgOGguj+I= + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: version "1.16.1" - resolved "https://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha1-+2YcC+8ps520B2nuOfpwCT1vaHc= + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -7745,32 +7862,32 @@ sshpk@^1.7.0: ssri@^6.0.1: version "6.0.1" - resolved "https://registry.npm.taobao.org/ssri/download/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha1-KjxBso3UW2K2Nnbst0ABJlrp7dg= + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" + integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== dependencies: figgy-pudding "^3.5.1" ssri@^7.0.0, ssri@^7.1.0: version "7.1.0" - resolved "https://registry.npm.taobao.org/ssri/download/ssri-7.1.0.tgz#92c241bf6de82365b5c7fb4bd76e975522e1294d" - integrity sha1-ksJBv23oI2W1x/tL126XVSLhKU0= + resolved "https://registry.yarnpkg.com/ssri/-/ssri-7.1.0.tgz#92c241bf6de82365b5c7fb4bd76e975522e1294d" + integrity sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g== dependencies: figgy-pudding "^3.5.1" minipass "^3.1.1" stable@^0.1.8: version "0.1.8" - resolved "https://registry.npm.taobao.org/stable/download/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha1-g26zyDgv4pNv6vVEYxAXzn1Ho88= + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== stackframe@^1.1.1: version "1.2.0" - resolved "https://registry.npm.taobao.org/stackframe/download/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303" - integrity sha1-UkKUktY8YuuYmATBFVLj0i53kwM= + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303" + integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA== static-extend@^0.1.1: version "0.1.2" - resolved "https://registry.npm.taobao.org/static-extend/download/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" @@ -7778,29 +7895,29 @@ static-extend@^0.1.1: "statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" - resolved "https://registry.npm.taobao.org/statuses/download/statuses-1.5.0.tgz?cache=0&sync_timestamp=1609654027495&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstatuses%2Fdownload%2Fstatuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= stream-browserify@^2.0.1: version "2.0.2" - resolved "https://registry.npm.taobao.org/stream-browserify/download/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha1-h1IdOKRKp+6RzhzSpH3wy0ndZgs= + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== dependencies: inherits "~2.0.1" readable-stream "^2.0.2" stream-each@^1.1.0: version "1.2.3" - resolved "https://registry.npm.taobao.org/stream-each/download/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" - integrity sha1-6+J6DDibBPvMIzZClS4Qcxr6m64= + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== dependencies: end-of-stream "^1.1.0" stream-shift "^1.0.0" stream-http@^2.7.2: version "2.8.3" - resolved "https://registry.npm.taobao.org/stream-http/download/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw= + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" @@ -7810,79 +7927,79 @@ stream-http@^2.7.2: stream-shift@^1.0.0: version "1.0.1" - resolved "https://registry.npm.taobao.org/stream-shift/download/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" - integrity sha1-1wiCgVWasneEJCebCHfaPDktWj0= + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== strict-uri-encode@^1.0.0: version "1.1.0" - resolved "https://registry.npm.taobao.org/strict-uri-encode/download/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= string-hash@^1.1.1: version "1.1.3" - resolved "https://registry.npm.taobao.org/string-hash/download/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" + resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs= string-width@^2.0.0: version "2.1.1" - resolved "https://registry.npm.taobao.org/string-width/download/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4= + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" - resolved "https://registry.npm.taobao.org/string-width/download/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha1-InZ74htirxCBV0MG9prFG2IgOWE= + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== dependencies: emoji-regex "^7.0.1" is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" string-width@^4.1.0, string-width@^4.2.0: - version "4.2.0" - resolved "https://registry.npm.taobao.org/string-width/download/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha1-lSGCxGzHssMT0VluYjmSvRY7crU= + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -string.prototype.trimend@^1.0.1: - version "1.0.3" - resolved "https://registry.npm.taobao.org/string.prototype.trimend/download/string.prototype.trimend-1.0.3.tgz?cache=0&sync_timestamp=1606008280085&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring.prototype.trimend%2Fdownload%2Fstring.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" - integrity sha1-oivVPMpcfPRNfJ1ccyEYhz1s0Ys= +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" -string.prototype.trimstart@^1.0.1: - version "1.0.3" - resolved "https://registry.npm.taobao.org/string.prototype.trimstart/download/string.prototype.trimstart-1.0.3.tgz?cache=0&sync_timestamp=1606008280265&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring.prototype.trimstart%2Fdownload%2Fstring.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" - integrity sha1-m0y1kOEjuzZWRAHVmCQpjeUP1ao= +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" - resolved "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha1-QvEUWUpGzxqOMLCoT1bHjD7awh4= + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" - resolved "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha1-nPFhG6YmhdcDCunkujQUnDrwP8g= + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" stringify-object@^3.3.0: version "3.3.0" - resolved "https://registry.npm.taobao.org/stringify-object/download/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" - integrity sha1-cDBlrvyhkwDTzoivT1s5VtdVZik= + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== dependencies: get-own-enumerable-property-symbols "^3.0.0" is-obj "^1.0.1" @@ -7890,64 +8007,64 @@ stringify-object@^3.3.0: strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" - resolved "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" strip-ansi@^5, strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" - resolved "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4= + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" strip-ansi@^6.0.0: version "6.0.0" - resolved "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha1-CxVx3XZpzNTz4G4U7x7tJiJa5TI= + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== dependencies: ansi-regex "^5.0.0" strip-comments@^1.0.2: version "1.0.2" - resolved "https://registry.npm.taobao.org/strip-comments/download/strip-comments-1.0.2.tgz#82b9c45e7f05873bee53f37168af930aa368679d" - integrity sha1-grnEXn8FhzvuU/NxaK+TCqNoZ50= + resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-1.0.2.tgz#82b9c45e7f05873bee53f37168af930aa368679d" + integrity sha512-kL97alc47hoyIQSV165tTt9rG5dn4w1dNnBhOQ3bOU1Nc1hel09jnXANaHJ7vzHLd4Ju8kseDGzlev96pghLFw== dependencies: babel-extract-comments "^1.0.0" babel-plugin-transform-object-rest-spread "^6.26.0" strip-eof@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/strip-eof/download/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= strip-final-newline@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/strip-final-newline/download/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha1-ibhS+y/L6Tb29LMYevsKEsGrWK0= + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== strip-indent@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/strip-indent/download/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= strip-json-comments@^3.0.1: version "3.1.1" - resolved "https://registry.npm.taobao.org/strip-json-comments/download/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha1-MfEoGzgyYwQ0gxwxDAHMzajL4AY= + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== stylehacks@^4.0.0: version "4.0.3" - resolved "https://registry.npm.taobao.org/stylehacks/download/stylehacks-4.0.3.tgz?cache=0&sync_timestamp=1603212834386&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstylehacks%2Fdownload%2Fstylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" - integrity sha1-Zxj8r00eB9ihMYaQiB6NlnJqcdU= + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" + integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== dependencies: browserslist "^4.0.0" postcss "^7.0.0" @@ -7955,34 +8072,34 @@ stylehacks@^4.0.0: supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.npm.taobao.org/supports-color/download/supports-color-5.5.0.tgz?cache=0&sync_timestamp=1608035619713&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha1-4uaaRKyHcveKHsCzW2id9lMO/I8= + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^6.1.0: version "6.1.0" - resolved "https://registry.npm.taobao.org/supports-color/download/supports-color-6.1.0.tgz?cache=0&sync_timestamp=1608035619713&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha1-B2Srxpxj1ayELdSGfo0CXogN+PM= + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== dependencies: has-flag "^3.0.0" supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1608035619713&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha1-G33NyzK4E4gBs+R4umpRyqiWSNo= + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" svg-tags@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/svg-tags/download/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" + resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= svgo@^1.0.0: version "1.3.2" - resolved "https://registry.npm.taobao.org/svgo/download/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" - integrity sha1-ttxRHAYzRsnkFbgeQ0ARRbltQWc= + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== dependencies: chalk "^2.4.1" coa "^2.0.2" @@ -8000,8 +8117,8 @@ svgo@^1.0.0: table@^5.2.3: version "5.4.6" - resolved "https://registry.npm.taobao.org/table/download/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha1-EpLRlQDOP4YFOwXw6Ofko7shB54= + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== dependencies: ajv "^6.10.2" lodash "^4.17.14" @@ -8010,8 +8127,8 @@ table@^5.2.3: tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" - resolved "https://registry.npm.taobao.org/tapable/download/tapable-1.1.3.tgz?cache=0&sync_timestamp=1607089091087&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftapable%2Fdownload%2Ftapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha1-ofzMBrWNth/XpF2i2kT186Pme6I= + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== temp-dir@^1.0.0: version "1.0.0" @@ -8029,8 +8146,8 @@ tempy@^0.3.0: terser-webpack-plugin@^1.4.3: version "1.4.5" - resolved "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-1.4.5.tgz?cache=0&sync_timestamp=1603882075288&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser-webpack-plugin%2Fdownload%2Fterser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" - integrity sha1-oheu+uozDnNP+sthIOwfoxLWBAs= + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" + integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== dependencies: cacache "^12.0.2" find-cache-dir "^2.1.0" @@ -8044,8 +8161,8 @@ terser-webpack-plugin@^1.4.3: terser-webpack-plugin@^2.3.6: version "2.3.8" - resolved "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-2.3.8.tgz?cache=0&sync_timestamp=1603882075288&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser-webpack-plugin%2Fdownload%2Fterser-webpack-plugin-2.3.8.tgz#894764a19b0743f2f704e7c2a848c5283a696724" - integrity sha1-iUdkoZsHQ/L3BOfCqEjFKDppZyQ= + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz#894764a19b0743f2f704e7c2a848c5283a696724" + integrity sha512-/fKw3R+hWyHfYx7Bv6oPqmk4HGQcrWLtV3X6ggvPuwPNHSnzvVV51z6OaaCOus4YLjutYGOz3pEpbhe6Up2s1w== dependencies: cacache "^13.0.1" find-cache-dir "^3.3.1" @@ -8068,27 +8185,27 @@ terser@^4.1.2, terser@^4.6.12, terser@^4.6.2: text-table@^0.2.0: version "0.2.0" - resolved "https://registry.npm.taobao.org/text-table/download/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= thenify-all@^1.0.0: version "1.6.0" - resolved "https://registry.npm.taobao.org/thenify-all/download/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= dependencies: thenify ">= 3.1.0 < 4" "thenify@>= 3.1.0 < 4": version "3.3.1" - resolved "https://registry.npm.taobao.org/thenify/download/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" - integrity sha1-iTLmhqQGYDigFt2eLKRq3Zg4qV8= + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== dependencies: any-promise "^1.0.0" thread-loader@^2.1.3: version "2.1.3" - resolved "https://registry.npm.taobao.org/thread-loader/download/thread-loader-2.1.3.tgz?cache=0&sync_timestamp=1603809370428&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fthread-loader%2Fdownload%2Fthread-loader-2.1.3.tgz#cbd2c139fc2b2de6e9d28f62286ab770c1acbdda" - integrity sha1-y9LBOfwrLebp0o9iKGq3cMGsvdo= + resolved "https://registry.yarnpkg.com/thread-loader/-/thread-loader-2.1.3.tgz#cbd2c139fc2b2de6e9d28f62286ab770c1acbdda" + integrity sha512-wNrVKH2Lcf8ZrWxDF/khdlLlsTMczdcwPA9VEK4c2exlEPynYWxi9op3nPTo5lAnDIkE0rQEB3VBP+4Zncc9Hg== dependencies: loader-runner "^2.3.1" loader-utils "^1.1.0" @@ -8096,61 +8213,61 @@ thread-loader@^2.1.3: through2@^2.0.0: version "2.0.5" - resolved "https://registry.npm.taobao.org/through2/download/through2-2.0.5.tgz?cache=0&sync_timestamp=1593479140504&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fthrough2%2Fdownload%2Fthrough2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0= + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== dependencies: readable-stream "~2.3.6" xtend "~4.0.1" through@^2.3.6: version "2.3.8" - resolved "https://registry.npm.taobao.org/through/download/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= thunky@^1.0.2: version "1.1.0" - resolved "https://registry.npm.taobao.org/thunky/download/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha1-Wrr3FKlAXbBQRzK7zNLO3Z75U30= + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== timers-browserify@^2.0.4: version "2.0.12" - resolved "https://registry.npm.taobao.org/timers-browserify/download/timers-browserify-2.0.12.tgz?cache=0&sync_timestamp=1603793837115&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftimers-browserify%2Fdownload%2Ftimers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" - integrity sha1-RKRcEfv0B/NPl7zNFXfGUjYbAO4= + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== dependencies: setimmediate "^1.0.4" timsort@^0.3.0: version "0.3.0" - resolved "https://registry.npm.taobao.org/timsort/download/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= tmp@^0.0.33: version "0.0.33" - resolved "https://registry.npm.taobao.org/tmp/download/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha1-bTQzWIl2jSGyvNoKonfO07G/rfk= + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" to-arraybuffer@^1.0.0: version "1.0.1" - resolved "https://registry.npm.taobao.org/to-arraybuffer/download/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-2.0.0.tgz?cache=0&sync_timestamp=1580550651593&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fto-fast-properties%2Fdownload%2Fto-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= to-object-path@^0.3.0: version "0.3.0" - resolved "https://registry.npm.taobao.org/to-object-path/download/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" - resolved "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" @@ -8158,15 +8275,15 @@ to-regex-range@^2.1.0: to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ= + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" - resolved "https://registry.npm.taobao.org/to-regex/download/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4= + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" @@ -8175,65 +8292,65 @@ to-regex@^3.0.1, to-regex@^3.0.2: toidentifier@1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM= + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== toposort@^1.0.0: version "1.0.7" - resolved "https://registry.npm.taobao.org/toposort/download/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" integrity sha1-LmhELZ9k7HILjMieZEOsbKqVACk= tough-cookie@~2.5.0: version "2.5.0" - resolved "https://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha1-zZ+yoKodWhK0c72fuW+j3P9lreI= + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== dependencies: psl "^1.1.28" punycode "^2.1.1" tryer@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/tryer/download/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" - integrity sha1-8shUBoALmw90yfdGW4HqrSQSUvg= + resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" + integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== ts-pnp@^1.1.6: version "1.2.0" - resolved "https://registry.npm.taobao.org/ts-pnp/download/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" - integrity sha1-pQCtCEsHmPHDBxrzkeZZEshrypI= + resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" + integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== tslib@^1.9.0: version "1.14.1" - resolved "https://registry.npm.taobao.org/tslib/download/tslib-1.14.1.tgz?cache=0&sync_timestamp=1609887446200&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha1-zy04vcNKE0vK8QkcQfZhni9nLQA= + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tty-browserify@0.0.0: version "0.0.0" - resolved "https://registry.npm.taobao.org/tty-browserify/download/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= tunnel-agent@^0.6.0: version "0.6.0" - resolved "https://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= dependencies: safe-buffer "^5.0.1" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" - resolved "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= type-check@~0.3.2: version "0.3.2" - resolved "https://registry.npm.taobao.org/type-check/download/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= dependencies: prelude-ls "~1.1.2" type-fest@^0.11.0: version "0.11.0" - resolved "https://registry.npm.taobao.org/type-fest/download/type-fest-0.11.0.tgz?cache=0&sync_timestamp=1606468837442&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftype-fest%2Fdownload%2Ftype-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" - integrity sha1-l6vwhyMQ/tiKXEZrJWgVdhReM/E= + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" + integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== type-fest@^0.3.1: version "0.3.1" @@ -8242,62 +8359,72 @@ type-fest@^0.3.1: type-fest@^0.6.0: version "0.6.0" - resolved "https://registry.npm.taobao.org/type-fest/download/type-fest-0.6.0.tgz?cache=0&sync_timestamp=1606468837442&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftype-fest%2Fdownload%2Ftype-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" - integrity sha1-jSojcNPfiG61yQraHFv2GIrPg4s= + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== type-fest@^0.8.1: version "0.8.1" - resolved "https://registry.npm.taobao.org/type-fest/download/type-fest-0.8.1.tgz?cache=0&sync_timestamp=1606468837442&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftype-fest%2Fdownload%2Ftype-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha1-CeJJ696FHTseSNJ8EFREZn8XuD0= + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" - resolved "https://registry.npm.taobao.org/type-is/download/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha1-TlUs0F3wlGfcvE73Od6J8s83wTE= + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== dependencies: media-typer "0.3.0" mime-types "~2.1.24" typedarray@^0.0.6: version "0.0.6" - resolved "https://registry.npm.taobao.org/typedarray/download/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= uglify-js@3.4.x: version "3.4.10" - resolved "https://registry.npm.taobao.org/uglify-js/download/uglify-js-3.4.10.tgz?cache=0&sync_timestamp=1609477758940&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuglify-js%2Fdownload%2Fuglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" - integrity sha1-mtlWPY6zrN+404WX0q8dgV9qdV8= + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" + integrity sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw== dependencies: commander "~2.19.0" source-map "~0.6.1" +unbox-primitive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.0.tgz#eeacbc4affa28e9b3d36b5eaeccc50b3251b1d3f" + integrity sha512-P/51NX+JXyxK/aigg1/ZgyccdAxm5K1+n8+tvqSntjOivPt19gvm1VC49RWYetsiub8WViUchdxl/KWHHB0kzA== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.0" + has-symbols "^1.0.0" + which-boxed-primitive "^1.0.1" + unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" - resolved "https://registry.npm.taobao.org/unicode-canonical-property-names-ecmascript/download/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha1-JhmADEyCWADv3YNDr33Zkzy+KBg= + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== unicode-match-property-ecmascript@^1.0.4: version "1.0.4" - resolved "https://registry.npm.taobao.org/unicode-match-property-ecmascript/download/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha1-jtKjJWmWG86SJ9Cc0/+7j+1fAgw= + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== dependencies: unicode-canonical-property-names-ecmascript "^1.0.4" unicode-property-aliases-ecmascript "^1.0.4" unicode-match-property-value-ecmascript@^1.2.0: version "1.2.0" - resolved "https://registry.npm.taobao.org/unicode-match-property-value-ecmascript/download/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" - integrity sha1-DZH2AO7rMJaqlisdb8iIduZOpTE= + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== unicode-property-aliases-ecmascript@^1.0.4: version "1.1.0" - resolved "https://registry.npm.taobao.org/unicode-property-aliases-ecmascript/download/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" - integrity sha1-3Vepn2IHvt/0Yoq++5TFDblByPQ= + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" + integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== union-value@^1.0.0: version "1.0.1" - resolved "https://registry.npm.taobao.org/union-value/download/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha1-C2/nuDWuzaYcbqTU8CwUIh4QmEc= + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== dependencies: arr-union "^3.1.0" get-value "^2.0.6" @@ -8306,25 +8433,25 @@ union-value@^1.0.0: uniq@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/uniq/download/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= uniqs@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/uniqs/download/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= unique-filename@^1.1.1: version "1.1.1" - resolved "https://registry.npm.taobao.org/unique-filename/download/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha1-HWl2k2mtoFgxA6HmrodoG1ZXMjA= + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== dependencies: unique-slug "^2.0.0" unique-slug@^2.0.0: version "2.0.2" - resolved "https://registry.npm.taobao.org/unique-slug/download/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha1-uqvOkQg/xk6UWw861hPiZPfNTmw= + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== dependencies: imurmurhash "^0.1.4" @@ -8337,22 +8464,22 @@ unique-string@^1.0.0: universalify@^0.1.0: version "0.1.2" - resolved "https://registry.npm.taobao.org/universalify/download/universalify-0.1.2.tgz?cache=0&sync_timestamp=1603180003399&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funiversalify%2Fdownload%2Funiversalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY= + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= unquote@~1.1.1: version "1.1.1" - resolved "https://registry.npm.taobao.org/unquote/download/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= unset-value@^1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/unset-value/download/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" @@ -8365,41 +8492,41 @@ upath@^1.1.1, upath@^1.1.2, upath@^1.2.0: upper-case@^1.1.1: version "1.1.3" - resolved "https://registry.npm.taobao.org/upper-case/download/upper-case-1.1.3.tgz?cache=0&sync_timestamp=1606859853284&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fupper-case%2Fdownload%2Fupper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= uri-js@^4.2.2: - version "4.4.0" - resolved "https://registry.npm.taobao.org/uri-js/download/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" - integrity sha1-qnFCYd55PoqCNHp7zJznTobyhgI= + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" - resolved "https://registry.npm.taobao.org/urix/download/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-loader@^2.2.0: version "2.3.0" - resolved "https://registry.npm.taobao.org/url-loader/download/url-loader-2.3.0.tgz#e0e2ef658f003efb8ca41b0f3ffbf76bab88658b" - integrity sha1-4OLvZY8APvuMpBsPP/v3a6uIZYs= + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-2.3.0.tgz#e0e2ef658f003efb8ca41b0f3ffbf76bab88658b" + integrity sha512-goSdg8VY+7nPZKUEChZSEtW5gjbS66USIGCeSJ1OVOJ7Yfuh/36YxCwMi5HVEJh6mqUYOoy3NJ0vlOMrWsSHog== dependencies: loader-utils "^1.2.3" mime "^2.4.4" schema-utils "^2.5.0" url-parse@^1.4.3, url-parse@^1.4.7: - version "1.4.7" - resolved "https://registry.npm.taobao.org/url-parse/download/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" - integrity sha1-qKg1NejACjFuQDpdtKwbm4U64ng= + version "1.5.1" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.1.tgz#d5fa9890af8a5e1f274a2c98376510f6425f6e3b" + integrity sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q== dependencies: querystringify "^2.1.1" requires-port "^1.0.0" url@^0.11.0: version "0.11.0" - resolved "https://registry.npm.taobao.org/url/download/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= dependencies: punycode "1.3.2" @@ -8407,26 +8534,26 @@ url@^0.11.0: use@^3.1.0: version "3.1.1" - resolved "https://registry.npm.taobao.org/use/download/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8= + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= util.promisify@1.0.0: version "1.0.0" - resolved "https://registry.npm.taobao.org/util.promisify/download/util.promisify-1.0.0.tgz?cache=0&sync_timestamp=1609969337408&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Futil.promisify%2Fdownload%2Futil.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA= + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== dependencies: define-properties "^1.1.2" object.getownpropertydescriptors "^2.0.3" util.promisify@~1.0.0: version "1.0.1" - resolved "https://registry.npm.taobao.org/util.promisify/download/util.promisify-1.0.1.tgz?cache=0&sync_timestamp=1609969337408&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Futil.promisify%2Fdownload%2Futil.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" - integrity sha1-a693dLgO6w91INi4HQeYKlmruu4= + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== dependencies: define-properties "^1.1.3" es-abstract "^1.17.2" @@ -8435,59 +8562,59 @@ util.promisify@~1.0.0: util@0.10.3: version "0.10.3" - resolved "https://registry.npm.taobao.org/util/download/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= dependencies: inherits "2.0.1" util@^0.11.0: version "0.11.1" - resolved "https://registry.npm.taobao.org/util/download/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha1-MjZzNyDsZLsn9uJvQhqqLhtYjWE= + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== dependencies: inherits "2.0.3" utila@~0.4: version "0.4.0" - resolved "https://registry.npm.taobao.org/utila/download/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= utils-merge@1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@^3.3.2, uuid@^3.4.0: version "3.4.0" - resolved "https://registry.npm.taobao.org/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1607460081656&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4= + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== v8-compile-cache@^2.0.3: - version "2.2.0" - resolved "https://registry.npm.taobao.org/v8-compile-cache/download/v8-compile-cache-2.2.0.tgz?cache=0&sync_timestamp=1603909569446&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fv8-compile-cache%2Fdownload%2Fv8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" - integrity sha1-lHHvo++RKNL3xqfKOcTda1BVsTI= + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== validate-npm-package-license@^3.0.1: version "3.0.4" - resolved "https://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha1-/JH2uce6FchX9MssXe/uw51PQQo= + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" vary@~1.1.2: version "1.1.2" - resolved "https://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= vendors@^1.0.0: version "1.0.4" - resolved "https://registry.npm.taobao.org/vendors/download/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" - integrity sha1-4rgApT56Kbk1BsPPQRANFsTErY4= + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" + integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== verror@1.10.0: version "1.10.0" - resolved "https://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: assert-plus "^1.0.0" @@ -8496,19 +8623,19 @@ verror@1.10.0: vm-browserify@^1.0.1: version "1.1.2" - resolved "https://registry.npm.taobao.org/vm-browserify/download/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha1-eGQcSIuObKkadfUR56OzKobl3aA= + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== -vue-eslint-parser@^7.3.0: - version "7.3.0" - resolved "https://registry.npm.taobao.org/vue-eslint-parser/download/vue-eslint-parser-7.3.0.tgz?cache=0&sync_timestamp=1608031066427&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-eslint-parser%2Fdownload%2Fvue-eslint-parser-7.3.0.tgz#894085839d99d81296fa081d19643733f23d7559" - integrity sha1-iUCFg52Z2BKW+ggdGWQ3M/I9dVk= +vue-eslint-parser@^7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.6.0.tgz#01ea1a2932f581ff244336565d712801f8f72561" + integrity sha512-QXxqH8ZevBrtiZMZK0LpwaMfevQi9UL7lY6Kcp+ogWHC88AuwUPwwCIzkOUc1LR4XsYAt/F9yHXAB/QoD17QXA== dependencies: debug "^4.1.1" eslint-scope "^5.0.0" eslint-visitor-keys "^1.1.0" espree "^6.2.1" - esquery "^1.0.1" + esquery "^1.4.0" lodash "^4.17.15" vue-functional-data-merge@^3.1.0: @@ -8518,13 +8645,13 @@ vue-functional-data-merge@^3.1.0: vue-hot-reload-api@^2.3.0: version "2.3.4" - resolved "https://registry.npm.taobao.org/vue-hot-reload-api/download/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" - integrity sha1-UylVzB6yCKPZkLOp+acFdGV+CPI= + resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" + integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog== "vue-loader-v16@npm:vue-loader@^16.1.0": version "16.1.2" - resolved "https://registry.npm.taobao.org/vue-loader/download/vue-loader-16.1.2.tgz?cache=0&sync_timestamp=1608188078235&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-loader%2Fdownload%2Fvue-loader-16.1.2.tgz#5c03b6c50d2a5f983c7ceba15c50d78ca2b298f4" - integrity sha1-XAO2xQ0qX5g8fOuhXFDXjKKymPQ= + resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-16.1.2.tgz#5c03b6c50d2a5f983c7ceba15c50d78ca2b298f4" + integrity sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q== dependencies: chalk "^4.1.0" hash-sum "^2.0.0" @@ -8532,8 +8659,8 @@ vue-hot-reload-api@^2.3.0: vue-loader@^15.9.2: version "15.9.6" - resolved "https://registry.npm.taobao.org/vue-loader/download/vue-loader-15.9.6.tgz?cache=0&sync_timestamp=1608188078235&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-loader%2Fdownload%2Fvue-loader-15.9.6.tgz#f4bb9ae20c3a8370af3ecf09b8126d38ffdb6b8b" - integrity sha1-9Lua4gw6g3CvPs8JuBJtOP/ba4s= + resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.6.tgz#f4bb9ae20c3a8370af3ecf09b8126d38ffdb6b8b" + integrity sha512-j0cqiLzwbeImIC6nVIby2o/ABAWhlppyL/m5oJ67R5MloP0hj/DtFgb0Zmq3J9CG7AJ+AXIvHVnJAPBvrLyuDg== dependencies: "@vue/component-compiler-utils" "^3.1.0" hash-sum "^1.0.2" @@ -8547,9 +8674,9 @@ vue-multiselect@^2.1.6: integrity sha512-s7jmZPlm9FeueJg1RwJtnE9KNPtME/7C8uRWSfp9/yEN4M8XcS/d+bddoyVwVnvFyRh9msFo0HWeW0vTL8Qv+w== vue-style-loader@^4.1.0, vue-style-loader@^4.1.2: - version "4.1.2" - resolved "https://registry.npm.taobao.org/vue-style-loader/download/vue-style-loader-4.1.2.tgz#dedf349806f25ceb4e64f3ad7c0a44fba735fcf8" - integrity sha1-3t80mAbyXOtOZPOtfApE+6c1/Pg= + version "4.1.3" + resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.3.tgz#6d55863a51fa757ab24e89d9371465072aa7bc35" + integrity sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg== dependencies: hash-sum "^1.0.2" loader-utils "^1.0.2" @@ -8564,8 +8691,8 @@ vue-template-compiler@^2.6.12: vue-template-es2015-compiler@^1.9.0: version "1.9.1" - resolved "https://registry.npm.taobao.org/vue-template-es2015-compiler/download/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" - integrity sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU= + resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" + integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== vue@^2.6.11: version "2.6.12" @@ -8573,21 +8700,21 @@ vue@^2.6.11: integrity sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg== vuex@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.0.tgz#95efa56a58f7607c135b053350833a09e01aa813" - integrity sha512-W74OO2vCJPs9/YjNjW8lLbj+jzT24waTo2KShI8jLvJW8OaIkgb3wuAMA7D+ZiUxDOx3ubwSZTaJBip9G8a3aQ== + version "3.6.2" + resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71" + integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw== watchpack-chokidar2@^2.0.1: version "2.0.1" - resolved "https://registry.npm.taobao.org/watchpack-chokidar2/download/watchpack-chokidar2-2.0.1.tgz?cache=0&sync_timestamp=1604989063099&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwatchpack-chokidar2%2Fdownload%2Fwatchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" - integrity sha1-OFAAcu5uzmbzdpk2lQ6hdxvhyVc= + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" + integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== dependencies: chokidar "^2.1.8" watchpack@^1.7.4: version "1.7.5" - resolved "https://registry.npm.taobao.org/watchpack/download/watchpack-1.7.5.tgz?cache=0&sync_timestamp=1607687479532&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwatchpack%2Fdownload%2Fwatchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" - integrity sha1-EmfmxV4Lm1vkTCAjrtVDeiwmxFM= + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" + integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== dependencies: graceful-fs "^4.1.2" neo-async "^2.5.0" @@ -8597,22 +8724,22 @@ watchpack@^1.7.4: wbuf@^1.1.0, wbuf@^1.7.3: version "1.7.3" - resolved "https://registry.npm.taobao.org/wbuf/download/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" - integrity sha1-wdjRSTFtPqhShIiVy2oL/oh7h98= + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== dependencies: minimalistic-assert "^1.0.0" wcwidth@^1.0.1: version "1.0.1" - resolved "https://registry.npm.taobao.org/wcwidth/download/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= dependencies: defaults "^1.0.3" webpack-bundle-analyzer@^3.8.0: version "3.9.0" - resolved "https://registry.npm.taobao.org/webpack-bundle-analyzer/download/webpack-bundle-analyzer-3.9.0.tgz#f6f94db108fb574e415ad313de41a2707d33ef3c" - integrity sha1-9vlNsQj7V05BWtMT3kGicH0z7zw= + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz#f6f94db108fb574e415ad313de41a2707d33ef3c" + integrity sha512-Ob8amZfCm3rMB1ScjQVlbYYUEJyEjdEtQ92jqiFUYt5VkEeO2v5UMbv49P/gnmCZm3A6yaFQzCBvpZqN4MUsdA== dependencies: acorn "^7.1.1" acorn-walk "^7.1.1" @@ -8639,16 +8766,16 @@ webpack-bundle-tracker@0.4.3: webpack-chain@^6.4.0: version "6.5.1" - resolved "https://registry.npm.taobao.org/webpack-chain/download/webpack-chain-6.5.1.tgz?cache=0&sync_timestamp=1595813319118&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-chain%2Fdownload%2Fwebpack-chain-6.5.1.tgz#4f27284cbbb637e3c8fbdef43eef588d4d861206" - integrity sha1-TycoTLu2N+PI+970Pu9YjU2GEgY= + resolved "https://registry.yarnpkg.com/webpack-chain/-/webpack-chain-6.5.1.tgz#4f27284cbbb637e3c8fbdef43eef588d4d861206" + integrity sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA== dependencies: deepmerge "^1.5.2" javascript-stringify "^2.0.1" webpack-dev-middleware@^3.7.2: version "3.7.3" - resolved "https://registry.npm.taobao.org/webpack-dev-middleware/download/webpack-dev-middleware-3.7.3.tgz?cache=0&sync_timestamp=1608052622860&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-dev-middleware%2Fdownload%2Fwebpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" - integrity sha1-Bjk3KxQyYuK4SrldO5GnWXBhwsU= + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" + integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== dependencies: memory-fs "^0.4.1" mime "^2.4.4" @@ -8657,9 +8784,9 @@ webpack-dev-middleware@^3.7.2: webpack-log "^2.0.0" webpack-dev-server@^3.11.0: - version "3.11.1" - resolved "https://registry.npm.taobao.org/webpack-dev-server/download/webpack-dev-server-3.11.1.tgz?cache=0&sync_timestamp=1609247155168&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-dev-server%2Fdownload%2Fwebpack-dev-server-3.11.1.tgz#c74028bf5ba8885aaf230e48a20e8936ab8511f0" - integrity sha1-x0Aov1uoiFqvIw5Iog6JNquFEfA= + version "3.11.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz#695ebced76a4929f0d5de7fd73fafe185fe33708" + integrity sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" @@ -8697,16 +8824,16 @@ webpack-dev-server@^3.11.0: webpack-log@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/webpack-log/download/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" - integrity sha1-W3ko4GN1k/EZ0y9iJ8HgrDHhtH8= + resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" + integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== dependencies: ansi-colors "^3.0.0" uuid "^3.3.2" webpack-merge@^4.2.2: version "4.2.2" - resolved "https://registry.npm.taobao.org/webpack-merge/download/webpack-merge-4.2.2.tgz?cache=0&sync_timestamp=1608705517290&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-merge%2Fdownload%2Fwebpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" - integrity sha1-onxS6ng9E5iv0gh/VH17nS9DY00= + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" + integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== dependencies: lodash "^4.17.15" @@ -8719,9 +8846,9 @@ webpack-sources@^1.1.0, webpack-sources@^1.3.0, webpack-sources@^1.4.0, webpack- source-map "~0.6.1" webpack@^4.0.0: - version "4.44.2" - resolved "https://registry.npm.taobao.org/webpack/download/webpack-4.44.2.tgz?cache=0&sync_timestamp=1609177006990&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack%2Fdownload%2Fwebpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" - integrity sha1-a/4rCvBVyLLR6Q7SzZNj+EEma3I= + version "4.46.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" + integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -8731,7 +8858,7 @@ webpack@^4.0.0: ajv "^6.10.2" ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^4.3.0" + enhanced-resolve "^4.5.0" eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" loader-runner "^2.4.0" @@ -8749,8 +8876,8 @@ webpack@^4.0.0: websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" - resolved "https://registry.npm.taobao.org/websocket-driver/download/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" - integrity sha1-ia1Slbv2S0gKvLox5JU6ynBvV2A= + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== dependencies: http-parser-js ">=0.5.1" safe-buffer ">=5.1.0" @@ -8758,32 +8885,43 @@ websocket-driver@>=0.5.1, websocket-driver@^0.7.4: websocket-extensions@>=0.1.1: version "0.1.4" - resolved "https://registry.npm.taobao.org/websocket-extensions/download/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha1-f4RzvIOd/YdgituV1+sHUhFXikI= + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +which-boxed-primitive@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" which-module@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/which-module/download/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which@^1.2.9: version "1.3.1" - resolved "https://registry.npm.taobao.org/which/download/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo= + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" which@^2.0.1: version "2.0.2" - resolved "https://registry.npm.taobao.org/which/download/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha1-fGqN0KY2oDJ+ELWckobu6T8/UbE= + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" word-wrap@~1.2.3: version "1.2.3" - resolved "https://registry.npm.taobao.org/word-wrap/download/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha1-YQY29rH3A4kb00dxzLF/uTtHB5w= + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== workbox-background-sync@^5.1.4: version "5.1.4" @@ -8853,10 +8991,10 @@ workbox-core@^5.1.4: resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-5.1.4.tgz#8bbfb2362ecdff30e25d123c82c79ac65d9264f4" integrity sha512-+4iRQan/1D8I81nR2L5vcbaaFskZC2CL17TLbvWVzQ4qiF/ytOGF6XeV54pVxAvKUtkLANhk8TyIUMtiMw2oDg== -workbox-core@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.0.2.tgz#2f865cfe633890b4210fd6d6fdb049a6daed0914" - integrity sha512-Ksl6qeikGb+BOCILoCUJGxwlEQOeeqdpOnpOr9UDt3NtacPYbfYBmpYpKArw5DFWK+5geBsFqgUUlXThlCYfKQ== +workbox-core@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.1.2.tgz#b694ca77e1cdf43c330f8fb29122946aa7e6a7a1" + integrity sha512-69rch7EyPsNAx5Y5YlSoHV39/EEE1oDeb5zmLIy6+mgB4BnaG6u/tlDtvjvKqHcPM0gz2L5SzYtTEvWmk5WRTQ== workbox-expiration@^5.1.4: version "5.1.4" @@ -8866,11 +9004,11 @@ workbox-expiration@^5.1.4: workbox-core "^5.1.4" workbox-expiration@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.0.2.tgz#ac01e8d17f48daa31dc0872c09ee6f4d2cf28ccb" - integrity sha512-6+nbR18cklAdI3BPT675ytftXPwnVbXGR8mPWNWTJtl5y2urRYv56ZOJLD7FBFVkZ8EjWiRhNP/A0fkxgdKtWQ== + version "6.1.2" + resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.1.2.tgz#0e31ff9cc12a2982430226cd7f34f7b16b3ddbae" + integrity sha512-86cXz8Ae5cAJMgJ6aD/8E1NMNON4qGnE4ir1G3VuOu1xLsx2ItbbXmz6b0BB2dZ+kX6BDwqE0wkgS5As5Sds7g== dependencies: - workbox-core "^6.0.2" + workbox-core "^6.1.2" workbox-google-analytics@^5.1.4: version "5.1.4" @@ -8890,11 +9028,11 @@ workbox-navigation-preload@^5.1.4: workbox-core "^5.1.4" workbox-navigation-preload@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.0.2.tgz#bfd9c61096be921b830153a3004b7212220748dc" - integrity sha512-7+ojLrjXmTFZBfGmUQIcBWB+xrFgXLMJGNQAtxT7Ta9A23rEWo8jqAgeuwAylebcORUlM+ztgYTV7eGp+AD+Yg== + version "6.1.2" + resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.1.2.tgz#442d085035f9d2f57cd123e8e2a9f1fa1f0ec3b2" + integrity sha512-A41yO/mLjHMNV1EGWFTDExYAYkNvdtu2U0deRNL3HKKEMomqhLfFHJVg/b2jyarMf9Iosm7jHFbbTr8hiaMWwA== dependencies: - workbox-core "^6.0.2" + workbox-core "^6.1.2" workbox-precaching@^5.1.4: version "5.1.4" @@ -8904,13 +9042,13 @@ workbox-precaching@^5.1.4: workbox-core "^5.1.4" workbox-precaching@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.0.2.tgz#cb45f290b0604bef1d9fc96bf42df82385d54e54" - integrity sha512-sqKWL2emzmGnfJpna+9RjUkUiqQO++AKfwljCbgkHg8wBbVLy/rnui3eelKgAI7D8R31LJFfiZkY/kXmwkjtlQ== + version "6.1.2" + resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.1.2.tgz#5d8d5d13793feb8119acfaa54b1a627bc766c881" + integrity sha512-jGwv6tMdIecsyBSdVCgXoD7bHxLRI972lvYOfvcosGjP3oFKe8p2DVPsn3TIzEVYTl+b3j59utC7yrOP9oEHSg== dependencies: - workbox-core "^6.0.2" - workbox-routing "^6.0.2" - workbox-strategies "^6.0.2" + workbox-core "^6.1.2" + workbox-routing "^6.1.2" + workbox-strategies "^6.1.2" workbox-range-requests@^5.1.4: version "5.1.4" @@ -8926,12 +9064,12 @@ workbox-routing@^5.1.4: dependencies: workbox-core "^5.1.4" -workbox-routing@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.0.2.tgz#8380bc322a2b1c44978df8ff6ae4e4d723f4e3f8" - integrity sha512-iQ9ch3fL1YpztDLfHNURaHQ0ispgPCdzWmZZhtSHUyy/+YkTlIiDVTbOQCIpHIrWlKQiim6X3K2ItIy1FW9+wA== +workbox-routing@^6.0.2, workbox-routing@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.1.2.tgz#e0e6a745bb2fb9110eafaeed0d35fdece0f589b8" + integrity sha512-aRcqO+KX9A0J5W6hEeEpGhT6Lesqd3WfgaqlSD5LRajm0vAgYnlQzY37w6uC55Ev7M5Gh/xg0lA99qKc6ozsEA== dependencies: - workbox-core "^6.0.2" + workbox-core "^6.1.2" workbox-strategies@^5.1.4: version "5.1.4" @@ -8941,12 +9079,12 @@ workbox-strategies@^5.1.4: workbox-core "^5.1.4" workbox-routing "^5.1.4" -workbox-strategies@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.0.2.tgz#f4383e2e5d46c1546e6e08048c9f5c9a7beb5137" - integrity sha512-HjLnYCVS60U7OKhl5NIq8NAQXrotJQRDakmIONnRlQIlP2If/kAiQSUP3QCHMq4EeXGiF+/CdlR1/bhYBHZzZg== +workbox-strategies@^6.0.2, workbox-strategies@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.1.2.tgz#3547eb17ebada31d095db98316913e1031b12352" + integrity sha512-IX7UNePHmmfb1dcXSxgcephYShnLc0pmP3MRT/TZGjv8f0qcZYH7Sr/lTmwaxGXQL8yCSCrQICZwJnHLw2G5Ng== dependencies: - workbox-core "^6.0.2" + workbox-core "^6.1.2" workbox-streams@^5.1.4: version "5.1.4" @@ -8982,15 +9120,15 @@ workbox-window@^5.1.4: worker-farm@^1.7.0: version "1.7.0" - resolved "https://registry.npm.taobao.org/worker-farm/download/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" - integrity sha1-JqlMU5G7ypJhUgAvabhKS/dy5ag= + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" + integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== dependencies: errno "~0.1.7" wrap-ansi@^5.1.0: version "5.1.0" - resolved "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha1-H9H2cjXVttD+54EFYAG/tpTAOwk= + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== dependencies: ansi-styles "^3.2.0" string-width "^3.0.0" @@ -8998,8 +9136,17 @@ wrap-ansi@^5.1.0: wrap-ansi@^6.2.0: version "6.2.0" - resolved "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha1-6Tk7oHEC5skaOyIUePAlfNKFblM= + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" string-width "^4.1.0" @@ -9007,68 +9154,70 @@ wrap-ansi@^6.2.0: wrappy@1: version "1.0.2" - resolved "https://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write@1.0.3: version "1.0.3" - resolved "https://registry.npm.taobao.org/write/download/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha1-CADhRSO5I6OH5BUSPIZWFqrg9cM= + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== dependencies: mkdirp "^0.5.1" ws@^6.0.0, ws@^6.2.1: version "6.2.1" - resolved "https://registry.npm.taobao.org/ws/download/ws-6.2.1.tgz?cache=0&sync_timestamp=1609271398262&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fws%2Fdownload%2Fws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" - integrity sha1-RC/fCkftZPWbal2P8TD0dI7VJPs= + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== dependencies: async-limiter "~1.0.0" xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" - resolved "https://registry.npm.taobao.org/xtend/download/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q= + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== y18n@^4.0.0: version "4.0.1" - resolved "https://registry.npm.taobao.org/y18n/download/y18n-4.0.1.tgz?cache=0&sync_timestamp=1609798602895&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fy18n%2Fdownload%2Fy18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" - integrity sha1-jbK4PDHF11CZu4kLI/MJSJHiR9Q= + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" + integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== + +y18n@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" + integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== yallist@^2.1.2: version "2.1.2" - resolved "https://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.2: version "3.1.1" - resolved "https://registry.npm.taobao.org/yallist/download/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha1-27fa+b/YusmrRev2ArjLrQ1dCP0= + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yallist@^4.0.0: version "4.0.0" - resolved "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI= + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yargs-parser@^13.1.2: version "13.1.2" - resolved "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha1-Ew8JcC667vJlDVTObj5XBvek+zg= + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha1-vmjEl1xrKr9GkjawyHA2L6sJp7A= - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" +yargs-parser@^20.2.2: + version "20.2.7" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a" + integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw== yargs@^13.3.2: version "13.3.2" - resolved "https://registry.npm.taobao.org/yargs/download/yargs-13.3.2.tgz?cache=0&sync_timestamp=1607208079987&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs%2Fdownload%2Fyargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha1-rX/+/sGqWVZayRX4Lcyzipwxot0= + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== dependencies: cliui "^5.0.0" find-up "^3.0.0" @@ -9081,27 +9230,23 @@ yargs@^13.3.2: y18n "^4.0.0" yargs-parser "^13.1.2" -yargs@^15.0.0: - version "15.4.1" - resolved "https://registry.npm.taobao.org/yargs/download/yargs-15.4.1.tgz?cache=0&sync_timestamp=1607208079987&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs%2Fdownload%2Fyargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" - integrity sha1-DYehbeAa7p2L7Cv7909nhRcw9Pg= +yargs@^16.0.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" + y18n "^5.0.5" + yargs-parser "^20.2.2" yorkie@^2.0.0: version "2.0.0" - resolved "https://registry.npm.taobao.org/yorkie/download/yorkie-2.0.0.tgz#92411912d435214e12c51c2ae1093e54b6bb83d9" - integrity sha1-kkEZEtQ1IU4SxRwq4Qk+VLa7g9k= + resolved "https://registry.yarnpkg.com/yorkie/-/yorkie-2.0.0.tgz#92411912d435214e12c51c2ae1093e54b6bb83d9" + integrity sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw== dependencies: execa "^0.8.0" is-ci "^1.0.10" From 45a0bda758d5c1c8c3dc222165c070170d319af4 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 11:53:14 +0100 Subject: [PATCH 83/96] updated transaltion --- cookbook/locale/es/LC_MESSAGES/django.mo | Bin 30215 -> 37513 bytes cookbook/locale/it/LC_MESSAGES/django.mo | Bin 36190 -> 36210 bytes cookbook/locale/nl/LC_MESSAGES/django.mo | Bin 29096 -> 35778 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/cookbook/locale/es/LC_MESSAGES/django.mo b/cookbook/locale/es/LC_MESSAGES/django.mo index 5537ad7bae23699ae1cba3a059ae8e2b67938456..a0ae2b905b064413e8f4dc9ff59800c2d7d12efe 100644 GIT binary patch delta 14288 zcmbuE37A|}mB(K-*%uPh5CRG0rL%Rm%0d>h@B2!+v$BNORj<1%T~)7AOLrOu3nI%X zyXD5;2o6j9p^aD z!?y8`vyOJVCOFP9@P>(w^E$k#)^Rq$YbS^8o}1!0pQZf6sgBd1emkO$vj*;iOjUHg zO6E8!Zii}cKkN&C0;}Ouw*ECZnDX1OAFP`0I48n^a3LHEhroSs7z|)t}|7 zWT6&x2uhGE;CA>aTmKu_kNKTHkkLf%K&^1(EXU~uC&6Q36l#FQa5r2DrJ*m__cuXl zq-@LIx9=aZ^*^=zg?;}UD9ybMi|m0j=rr~Wj(}{nCzPfhf)em2Py;`2-~SG({d=$x_Ma09l7U*lp*iUP1Tt4r;li)LYIr}CAWuUH z@;sE${3q0kPnjD|H~~t4c~C1~1l4a9RJ)D#eLa+I?12)f4N8DZie%K`8vEjNPy*a+ z>+ggb_+BVMer(G};cCjy+xqeI!f|Fp4ZIL)qBT(c>TP`to=!OpwI#)`kx|1t;qmZ6 zxC{OQs=;hpYvpU;HdugK@dHq*e#G)9lzaUeYAgO|>m&0WX9DHHQ153$EoeDJLq%tO zm~pm4S^1ez1ACS!xR`P~Y=hs0a@Xnnkp}id33MBj=Kc*{1|PEZXAm4T-cG3T8{k>6 z+0?WDKO!R|djbxJFF`eY4{B>7i^6h0sDX}!GQN|cG&32FhI^p;w?nD?8Ys!4QpCHwwXxSjG3U@aWFG_;ZVP#W9_ zCBQjQ6Es6Dq!m`dk3k7~k>w|svj1mOQKCYseFJKszd;$x&}E@UPJt&<9t)?yg-`-F zK|IoFg(tvoLJ5Av@po7Hy`_ics=usEJ2Fbr=Vw$|;uf zq1s1>~k zHQ=kTH+&OHW$!=@(0ff-KNM=uheM4s(sDf1UQdVWzY1#H4Nw}{4u|UeZy=+Ab5JX} z5K8hZpgLY}>pP$(It(?@?NBTGKI{V@gHrL6Q2k!E^}mN2|81!Lk+qI91NMQn%I1`TAz%>hQfwSOEa56j! zWjj?HLpMJj7Ehw0mW(7@0VVlbNLyz!lqNn82f(jE?cwcE?fxAqUOWZ0=dVGve+M?f zzMC*$7{I;o)36`>1Jr!)Y(oF4_!|`iVV}*Rs)kvPhPBjBg;Mnn*cUcJO_a9v7ufPu z@MP-02nqkr_uy>!7R1q<+AU%1-w!!Bod>s||Fg)vPsPRX%&noMFF>ty;Wo!v3im*? z?pz18vR}bvaKjn2ftSN5d=OT_KSQnXU0Z%1j;9>i9&W)zsD;ljl938mz*}*zov?}} z_O5rF=cw;@CYquCW!M1ULfTrjI|oC9#eLz`z1~Buw7<83I|B8$#X=)(_Z<^qKMs%M z{fkhM@-5gO7W+4b)>{n~Vo!#0k6F-#E8rj)gQvm_+zGFSa5}&nch@vhg#8Yr~y(i3G;9Od=ct=e;vwL zk7)@78Up)Mo(v`UY$(Ck!m)4{)B?`8_5T9p4Y$DF%73f->r7p~iX3zJCvDp;a05F9}b~ zgaXWk+RLR-9oO5k2NzRrfm-?3p;Y|?D7Sh54uMa@q3{(b0pEq{*Y`lE;nh&8KND&z znu}!OWDY^8?q#Tz{{`a0&g^X1;q#U^Tiy;e!97qDJ_fag&%q_|Z75?sEf==i0FR}- z8%l#smc=v~-Bb!t16&2=-#5Wa;CpZ#yeJyd27l9*5QNXHe~4 zg>-TL2(@CrHDnQD3q|KTGE&{0P!c`_rP`;VR`w!14!#Lj!(MF!CAa~~n68A<#9^p~ z+zlUvPeP5`aWEYB+fahtYxyMXC;xwijEv(AD0g}nYL9xihbtHcPoR7f)C#9VwVMMq z@p34^w?g$h$Fc?1Qa%V}Y#neCyu-eK0ghsR=l5jfh6BzEB_0B`^3jm6@63R6;1zHf zJOYi1;RwpFT2`GO3NRAt5UPb5X9|>ni=ZOsMkqlagGCMSbKBr8C_$?JDfH*Qa3qRTbm47K?Vo_s%u{e0`~@5i2V4-2GX{>Kya>v>&VkZg^9AT%M$$@!B)tG? zudlMa0cxeUL#_M)I0Zgq>wAAJ+`5zC$<&X5nqU!>4XuHicq`Pn2cWj{<4{|E-N(?s zB9)WFYN7*6;rcq#R7L)D*uDC~H#WeI8pH$qKt3)BQZfG&Ijo&?{7@`6Dh z54Ug>)B;~)Se%O>h}vMV|pEG!gry@slGTA z_#~+MS}4t|fU>2tAzM*&3iie2P+Ra-r~wZ{srD`?)jj|WI2kU26JZnlCcGL>lm9Qe)N$&l*bn!?AHp->sh9Ed3e3O>aN9qJx7jvW zOZf|MG5irc3m)@{uzW6@MEOf_B>XWv1-=Ajj8&fu1sx|czcYo*9ykli3$B3Dz!%}E z@D|t)J_Mz@|A2C@*PvD!xjg*EqZ&@7d_82_ogc#iaN`x>?*u!c#@!3GrA@G?2@7Pz zOW`#5IVhF?2o8ilhf@7-q4qp-WhlULmbGvN^-JMWcnC_9N1!xYb5-~~(F${v?}InM zIaj0q7BWv=9jbW6HC)FiC*U%8D@?*aKn;A>wc)+~3-C0`N8vGW;HN^r9|Cb2=Oj1< zj)W3?EtCcupthm~s-5i5`4_Ou6!^NeoCp8-)S9SOWvnf$*jI+U-mI zFJU5W}3~3PQlpcambS@w*v~}Cb*ONAA|JRZkMXEfLX@r5A zXS40V!DycOl)pyqR1)_QXC~$E!5C>e`J3Thcp^#9cSsMCqNIM*odNGBrAZHyu3>)X zINSJ->edhjgsqlDb$yQGbFaI)t4yyXJw`;$K%PP1(mQ+|_lCTR_Ijid$S z_55cD=iHFt{eQddsJbCGKa_kssXyg+;4F9^e46wvQeV=`q-N?*CA~mi&(07gUVN4O z7~cH}UP4NcCkmTqCVvO&{634yHz@3fQ%IHPT=H!ceo3mcm0y50)X#-KvUS3*ZGJ0U z%llee{;Opl_&(`1(nX|ww5fqc|2r&WRF=ta)C-hhuI2T}xp%X&-4G=?T)aTK{Qu?4a-~QqN}&^-oeUhct?OAJTC0 z(`}ox|6hx zy4j?2NP2E3^&I!^?deHsAhii+|A$HNIBAr zr1f+xz^U*lI2N7-N0RARa1!tCBVA1@?y)Z( zqp;HE$vT62WR=+T`4ZAm8k^CHRx|V~LEPbG>xjO$T{D7hNH8r|L1=A{{t zY2#V1$xYI{ahl;5N08nAeYD|f^^i~6BOJSOY@Ss!1dyBgps^v1kcSU@>*{? zZpPk?Xz6fV2^p?Y4CSomaz`818Cem(@jr&>2 z8)R6AMvVJ;FOftm(r?tQZ}ziBl^;}zQDW(15Fr^h5{Wr1ByVqTU_WbcqMA7o?-ChMV=?uD)}mXwZ3^RXb6V!4GJYV!Dl z9$9E;wb-vpO+I5}WhrKPalbKvGTBR85q~hQ1ok*Op*2yi5i^!BR9qHuNhm=eGIDB-@RGvVJRrm@#YOg$%oa zCFk5)KiU*^w;F}XnKmbKvFIeztUm3fjFEg`HlrE6V07iXb=qT9MpWw=3`#rs31T*A z9|ooTY?B|i`+H#Qh|dGLUCSc&WIcGV(x>}xQa$5@dtnp}5 zs>}NslkwcsvT=7C*3|AU4+kl49^VqFS#Iq-SFoANhU5}WI7%VEwEW!(8zXKSXG5vT z6^h-p%%EXEl8h<+ed2S~ZoN-9Qv}%Vn@x%NrKfA3D0NJ_c7UIYWfK{RT%Iv`P^7x~GQ%>DTpvR;0~=$AdwI`Y>a0&yq}Uz??H)BB zlB@co1WQg^T{Xnb1+fGNg=f|L&FS&T)D}!hlBB)X2Fx&*S5(5kRM*3=GhUM)Ee)Qz zv*=}8;z1jZCQs-1V0UmuOr8X=TwIe5=1S)02D`{FuG!Z>{B5aOVzvu6#e%&hWp8FxWZ*VGn@SMQvDnhSSr5%fH828^ zfQZwoAmVfz?p9+_Ih5q(bI#Vr#$+PxmlmJ)<|53BpyO=wa=A8QI1*9R;y>DEP;CN7 zZ19<2OnJiWMUm2(b1v*98!R22vuI#lA%j#b)6bU%&YjwOrF^R#ojWu#Fcb=VKA0~r zocB_sM&7VK?bL}|3wft5#o_PNgI(xI%OE=m2Q&W1hB8;j!6kHRmg?(0%x0G^wb&(f2coXQ_mVARH3Lj#G)I z<~(D_cl%I794TiP{IF_wBL}UV+^VZv1{==fekyQVIRH@47^hwyXAgFAUXpV<-i{5W zTS5bqvDZ2VCaTqX>GsO0 z))?qMrAiEl?ae4$4RCurwrg&Iv&SA@#?C)#h)T4`4b;R|hH_$AN2J&-r%`X3*Wo^< z{XBNnQgPiJfy2bv%8I3k(5s_HfOudm&y1pVG-ZQACcNvR9vp?;o}iRC*4$M znM-WI)rYvA?!3#DGbD)JI*JpGoPUH2reV}X+%PSJ;G)D4E{U~vug87%G;<5-irnF) zHpVhNw?GQ}YPzIn&R;G?e(Aczse=Qzp^%GF>A43AIsh9F6cT2M?YIj|MHRd=4Rm3R zB|6JoKXHC9u0dFf7Qi{~r5X~QUr)Q4g3ml&=eNB$cLB{VS>1NBZoczyUh59;UBzU< zZ{oshr_qutl45>br?C5Q1S~sSna^COq=KH~b@VyLUt}OE*IP$ z+Ba+R8nS4Gg|=d4Qed7~#?m-D{hai6pwM}kpx#rNSaqmPyAkFF#0tX!G#GZ0$uh<{l;bm#sgcUJv(&i$q*8ecd`n8PWA6kx-!GyyVE^L&+<>Sbwm8mjtEVJN6IUW}Ll| zi+)hLZ^yR=5zO?-Vd7;u*x48v!smwZ^Kd<0>B(K^&EMqdJA%&wt8s1v7*uCR_cw@w zzS()|k(#d%-;W2`^5)%lMEXu840C-b4cJ>(T%A-W4aI9lApm&|I{f%DiE$qY^pz5I zkKD74Ac%0>8p8lDchl;6^tPWYn3rrWkN0tx3v!jO6fXV&sxhar!xGeU*8gD*!QOYO zPG6l)dgo!!R-NHx$k~KP`n-u@6~>U#a+)sl$9+qep1pHq9KSC)$15Wv6+t_mcvr{5b~R>${Q2=*@XW&c4s;}xL(5B*~QBX8U{qp z-_ozn zj~RC?9r7CnnG+iMV~ANg>d&kG@N#nH!Htt6wfYR}xyqcg29r@JbZ1~p{IJrHNOC5Y z&S(m%;(qx^)4|AbAG(^9>J!Cz>(c~By5{&5lv|`zr?}*7^HF@~w*$w#HdEOK_S2yB zY~tS<}=Iqi?->Yxy=$bwD+>Z zW|D4Zfi6lWklSOWp7rw2y6I%oUZ=kTL&Zh4i@NjVI8!(z!y9Pn@s<(gJ6n!Drg)@d zwQg*Ug|xYtC$<0G8`v$Ubw~3#7+$th!5D18^bYTDZaYqEBBi1PH(l&C$-&={r6uij zENI&*ZQQiqRC+FbQvU?eRX?vqOYf(5OeCOUl^AiJrJ^6Ls{7L29pPJo(@Qt*KE8ZM z5RLRfLtJ!9zs+1%N+0<2@yyoQp{j1X=Le|+LA7GDPU3Vdi~fmmogJmivx%ZP0F3=` zSFv*t7t9?Kt%aW-jA!j1?4cd^2^z`BE{uq*UWxvTdYoWfwxlHFV%{FD@LH;%Im1JrK^+vM?yE*rfh-J zrJY~XbtdVHHMA8gvFYuZPtsT-%3gD4qh+Jl8f2%MNPs07yVkv~``eTwE?RyjAC3Gs DL?YAW delta 8027 zcmY+}33yc1-N*4WA#4GGun0sT7YI8fA#5SCg(V;Y0#RH*Ws*#A$YdtWf`H42xPgMp z6$NWiM6K1L!U!UWBB{kv7pkZz?$jz3QK?ofAn*4#_eg!u^Ze&?&Y649es2a{{z%5n zM|{bTT4$~{r13suI^l>cV>XeW(^j>{IA!!FlQeC}=z<>D7z^+W9EMGB0-lZ2uqCd* z)_5N_#ErH-h0Q6~V?OS~MtBNKuu)HA24g9f;zDdi|7IH*CT;$TZE!!TgD-I|9>>l& zr1|9Vw7?eF26bOIyomlyZ!(Q>sl8x1Hle)6 zme-@cf7;e>v%X}%--}w(_ize+j*YOWk1-u^IO_YE*a|O0O*Dc@&3qY|Cb$Y!z8A~z zAyh+$k-akCqGpuQ*K4p9>X>vwT{jRl!(!A5PQ<2o3F^Ko)D}ijD{_5b)?XvKnF@_? zjlJMu)D6#IHSR_Ypie(z+Tq#g;0)AEqNoAfgc`s~)P(Lwwf_jJ!>y>5+=05jz8~wa z3-{U!-a_s50n`BggISo_-@BnDs{Tw=$9cBC7}fA-)Bq;h@+_P{`7&GoFskDes@?5L zGHUQ;d%;`wi_fr_`ma$l?>WG`t{AoCWvKeuI2~(IGkgJ?VZHSYY)<(gY9+q3^*>`z z%E^ZL-UaCqky7hq)M+h8HGHu(fFmg{z$@`7)MM7Gz?*ReYCwjG@5=l?o;!3tDIYfvk(E`5P9kJ|Fns2OcTZNW}#fN!E!>>bo;|JarfqxSfi zEuX|5lp7U!1L}`G^!%5Q(P5g4>L8Aq(PGpLmg7uZgT3)9%*M8ZybgP!W>|pK{6lPyhp-IG0CP|c z)>@aK27EKB{o7CjS%X@s2do>1u>M-g9aLzqUPCo_0CmG*R0H3lw&a8@Hy`TNcR<~j zhx%(+fEw7KVZ5Lyk3f|#_90P2u^ zf&KA2RKs0{+kv3U1*jDmg1WxMIv(3no`$+ESxH7q8$``;0crqCQA>IkYQztq2KWT( z#_gyMcA+|W8Fk+qsFnK!b;!OzUH@NOua|_{ZH(NXG;PTgQqd86<7DiKF`R_=;l+3e zN8w0*3~a=!QP=ey!2!h?*asIQPny|)7vS5dE$+wLstu0BjyMA|_59b6(Fp5sGA=~T z^d;2N@59b`5Ov+psD@6Vwyq7M()C?&9u{IAuE9%iCu*-djP_QnE2`WRo6)~1AfqKY z8?^$HP)oT0wKdnHI#^-r*V^*q$fB6%kO#(mkNRcPXN>not-%{8zk(XbRKCw~VLSXB zb?Ae^U3FhJlr~#Znou%w@Z@`@}PPu!Mj5=I{n$ddH z2%kV5w&zd{yoj3VehlG3RD+Yw_x{?IqaM@wsDUg*wRb1B#^0d^{3P;=+`M4R$ za2!K*IF)BcHhYU} zoUNp(Bh!wG1nP!cQ5`*qn#ohx3HPE_;0tVnM^O!C(5tR%g&KH2yb?#Dwq`48E8a#O z?jKMC%DYGdW&a10(F{hS9=B<>JPXy~JXA+vTfQ2#0?TZ96*`nxV|(0+YUg$P{X3|M zeTW*+G1LlW^Hyt0|0aiwZp>2!jzHcmrVKUH8!&xFFq`sv)C^Lnf!Cu3xF2=jXQ&l* z*jGIbL$M={L#@!ISc!F*{`9^;g| zpl0S;H=_1>4{C+JKn?6i)CxAb+?!BK)Ji&+v;MraOc52im_W^FHEQG=Pz^ngYUowe zKn_~JLA@ax%=PxX3F0s1@mhT7g2;Q&xt$Zc37jI=l$gK{e{eg!OvtP5E}z zA=-uo_!{b|IEflSj^7(-E^5mPkX1Hga0uRy+WR+A6Z_nn{Dlm!V$;6DTap~qK>FiS zJR3Ejov0i4+V2mcIzEOu_#+O))|@N{$D_Uvpk_QD2VfoQ?5soXOPVcYx>B(Zb^4E? zR^$X~>9VT48D*pPtebT(YAec6GrI))VXduSi+T(H#^=rF3m?@$e92E8TkfZZq$M;+QZsP{?;HK7}D4BmxJ z@GVU0ix2Dt|H4elKcN~piQ4-!=6jD>4mPAb7&U_uTYnB}rj@7;uSKosJ+}T&sFmD< zTA|lbEA;++)?YV%LxpCRRpTvXYg9-5P&W=lEqSr6pNxGePsd((6%N1+SdM>3o=npt z#P2-35kJOvu_r!T>-|LgsFwZjO+|yS_v-AAyo=0yJPY?&51|gtDb#?vMm&4tWXc7o z$8HH~#csvUxCXV*ca5HLUU%;059;)NRI2KLRm~$XGj*OOSCC2b;d=UK?C*obABR9N{rxWF~DKtiK-x-tozC%JGH@8z=Mp{0cd_-_Mx`%^!F+cT^HHe_>g4Mw8$<9Q zq<F9Pq6ODpjGb`_ zo=f~TMJPOPD~hm~;6WhK{}^uif$VZZC%BOEK)jb2Npz>I6eKPrx>EjwDo8I9JSe6W zb-VDliC0DXpXguONO z^6U5nF`YO-_-L#-t|FAGJj``iz;~D8PNJ6hHT_5?gK&sWgi=cD|2T1iXiq5ZCOXkb z-*n0Qm<#_Qj(bIO5Wgp~xb6;HS4_SqQ9-!})?-&{ym>%YZ}?>23o&6eWmx;P{qI4x~2Gm_W$o>#&W}1 z_NKO!pC*PAN`=he|G0HeY)`yVjt0lm_*Dc?j}Cf z3;!sY&BU+i4KjJeI64_hbRgDI{+MV$K986}z9FGhNBog^QU#k*FXnZ~YFAa|OiRS0 z!FVtdHl>uxgmGCKDTqxLATYQSKWUMTAo@wILqg*8d8zU9a`^e77WjG zW(F#Qb%9taUOXWq^;*g0K6mzr@(qhe`rKPaz3k2%-QG=({xJwch}U-sYd7B>vM0P z(L1$p#x*|2AFB2baYl%uAp-}GnOEx%hVm;TwWInwMTJF$ZkO`&n@{nF=Oz5}0wqo$ z<}N6o?Y>t&Jk@S?O{V)u?`(JZ<^5*G0#PRs^H)WjI)BvfR7aw<{&>J2b*k&vR|Z41 zfp9$F1VTn+{U?{l6?}YqLMX(|ijKl+#?#at%4o$as`i{y- zcwrzK4@RAM!fVY5gq=j#sfdJw@rZLpyf&2YO!2!{&+V976>z5dqcv5LE5lAK;M64o z)C9t`5s&(#S?;v!I=VaNPRjdrIHiuh3WgK@%3yseeNQl48A>b;I0-k?->pksG*aQO z2nD?P#1hrP%Als^%_vpw-;?Q%tu9F2QN7!j3SaT0FExHX8~0$%0{5&?(7hw{Wa`}7 zfY03(UYv?Ww)h%5;fNEfPq_sP%3GgPTNjDO{b3f7GZ2XTW2r&WpE7c%L}Cm&6S~2HeS4u5i~cn%Lli zaM1l`(f)39t)*X(2sjZIhn^x~CmIOU)`k2_{8j!~zI$ZxVfXNoqVDI_n9@*COAvAV zOgnah$*rUw{m{icY! zecAW!jvL-djk>8@1NW8Xg^eo{(O7Vy-}SAyphJJBF3L!w5t^xB`6{D2lZmi<&5Gh| zRsC;@(O4k0XGNheBjUIxZ(ZyD;kIRN>B>;&x=2;DexqL-Mep1l<48m~Y+4m}*UDh( Ol~w=rrRLl@!1sTK>3CBB diff --git a/cookbook/locale/it/LC_MESSAGES/django.mo b/cookbook/locale/it/LC_MESSAGES/django.mo index 1c57ffac411fa80778660c36d26f581a5fcfe291..85a17ed03f3afe10b5078e2230548ae21ec4d8e0 100644 GIT binary patch delta 2991 zcmZwJdrZ}39LMnolKUM|@rK7sbD&r{3pb$BLEds;DQej4a4vWhICMB@QFat1)R0^! zYhKb+thJU|r?gA=+ z9?Zg@Q2lSB=85+ila1-9qs_&53{9h;0n<@uU4iOYjoQgtT!*jY7|dE>Juko+)XOm+ z!>GVcq89uL6~JYjfLHAH%#~LAFpOn=lSd(m4wJ10Q;dn!OHdJ(VJ<>5H$1z3kmQD=S*CtwdQ!9*VFh}^b5Ok#agM?pJoLZz$)Q*j$Uj2(8p8&jxX zwY`bTK&;;~1$C5Js14=fES!uw!X|taZ{s2?swe-7=nV?G-`jBy9zsoA{+t!aBGk3= zq8DpW@5n{e4zJ;O%nn%n9z%_P+;$#jP+x%Q=*8){Izav>QTUt&eSm&NO&rr;nS)2E z7oe_RAL=YKg4RS6Q4<%V7A(VLtgv<2)}uDM29?2P)P}YO$$t`sH))XjFclBl9gm|j za}M zovg=b+=`kojLJ|4^3NRSKlPis+6r_!Y6FW=JFG@!wic)1W>m(yun0q!C@AvG=dC~{ zp#~P9j;0s~VGXKZGmgUDsK8I4GItvF(p^Mls2dgVbsU1`1*@Ko3LqCp>;4x~&<>tK zO|SyBPylr++U@r3sDXP?JB(l^cA^5lWVd(Q^{c3}{u9;jE^2&6lQn)UCg}c8p`eJ1 z`WtxbQ3IYvMP7@8u?2_WF4WFGLuKX+s(%k&#v7>2oO#ij_dK>m8S@Kjqk%P603l3a zebY`sJJ^MaaG&j`m__{*j>K+Ms{g@kjCt9bFbDNvnt-|mb*PuH5tY#g+MW@8yv;&yxz|H9Ka ztJ(TsrLVWXghh&|gaz-tR1z$Zq&pd z+Md9%)W1f(ynPspi5snP890=BXtZ4@L><9GEX7(>01>RiUVH+bo2=h_2XP7YA8;EM zZnl16okuNP{Hm2%Cl*tG7i;im)V%ZC`aeK3%vK5$Y4{TLrMrdkcn6~}c8m4rH6E4v zeAIVg7Al2LMa~Z1Fn2_a$5HPL_`$W@=UgQ`4!5Vl=k^4`bE^s?`>WoHD)!Yms%rc$ zm*33uyM11t%jvk+v@4kJ0{j+*gKm&?=8 e5bbpH&9z*vEHkyuhdJj~y+52^|Ft<^=bYd9eb4uN&+qr+ z-f4@x(iZvE(D=|wW6Z2VV}{}ZOv4UL#2>Lg-oR9Rgwt_gkum*nA?Dz6oPs-WDxSq5 z7~wG{88dJIK7+&Y1o%{?|ATPhlM1 z!YF)*it`Wl#ev1flwumjU;`?lmg0~d_=JIU1`awC&Y&{y!dSeD%J?Q~UaZfU1k6H) z%tU+)+faeqQ3)MEC2|rKuN$?oUr~wN4mlGZpl*mQp)8n+(O84JaU&+-9*oD&P)8L; z-PeUm;4%)vE2#N*QE~eCjTww_sH4rq7z|CMp&O>5&Uz7QVj*fL>v03_z$Y>3ZF@Zj zXVNdgvDku2>|4}=7f=a&hokYTGoDat$5XH`>zgbZaZDIv2TU%;($7O>I1fkS5*&uL zsM7C40+`QHi5)>z>IYOJ*B$Spjx4gw#?8Rl^haP4>zhg%%D5g=u(9`oF&{e~MlE;> zwd0GZc}eAVp)Aa#pM$G#DeBD6;b^>!%P@+II--@19*kpsf$ zi&3wY8;jA0dPXjxcKADHV{*XGn~J(W-*FBOp#KW?M>pnUAVB@c(KyC{K0v>q0-Gvp z8h%4J2le{hMxAAR&<4sz1gvArKpXrMOCmCwV|dU^^c?RJ_B+;CgMS7 z;&D`E&Y>Q{pD-DttBsj}Lof;FqrP}=V(&tzoz^J2ug2s0}PZ?XVD4*%Hjf22{mP;WP|&(@^FK zYi%MUQ8(tGjwTmV(1)5=i^K6lRN^O4l{<}k=q{lu)PqX+20o6DoPP2;n?NQ$q4$3> z4ej6!Q~)n(p>ot)vCSFZh01&%YKMn$Af7}e-0h6_IQ?s=v;Gq`?;+~`_!@ivFzl!I ze=H4UJf(Mlryg~~YpBdiFcs@D9rvPkb`({aPSpI%*n>AwmFZk><6gw(2xERmZM3}B zCQyS3tZ%l_&<^&ZGTiU@B@UwBff?9?D)l`ajHb>8OhbK`o<_X|e$+!)iK=KdYJM&1 z{ymPLV(uwy5t)Bhe7=r*d9cTs^N$XYv3M7x+!SB7U9P^r66{cDc5P^G<(3K&z*j|fb}5jX>nq8}A-D4)5x_!6$bowyip z;(5&5Xg^rdo9vfx;wA#m;zAVzuj6s7#H7vk7fn5m(m3{hpiq@D4gBqgA*jUiQKg@a z1^6i^gc3g#5a6T^BW`Faw;WGMN zxEr&#+n-n`Q45c3vXxzciuVDQVK*x7^yc0V&`k3#jWGo1+s*g z00t*O^5~DHnUDYpflvY@5K0QB20|#I210=M{oOk&i#+nj`@EYRe`n^-ojG&noHMiH zC$EHl@%@Uz3%xpg&*EtcS=K<9tFo-uDL>X%t(Mhrlx1zKw5&M1gZh0#E$aYm8D?3F z>9=XPWgP;q8ev&)!K+7F)^d2!=%C*VV=U_u>OUWASzY*UL)fww!tIc$3f8q0deU$! zREGy(C-^w*4WBXXZ^G`>KZKoOMU7=00juD2I0POBx5Hl0gB{`Nru}T#jrtzQ5Y{!Y zlKHKtDNLi`k8l#~dyHkxh091rzP#A_9U?$uQ=R;ZOa`XObD2tR#{T}oF zQPcjE;h)U=*Ptx-AuO;5R=0`l8SDqyYRiTFU;^s>S+EDZ2=<0QgtEjPP!r#8>W@Gv z_Is#3{xj5gLosVlI0kBgGoi*^HVOOpp|Hs`B%nUn3AOS9>;*4?GUYy~0j`IK!TnH{ zdKgN<$Dsy3VBY@?s{d!O4tALwD3XR+!0D5*|KSwQr@@9lg1zAbP>MVUrN{v&r+Eiz z#ez!a#J&w%=_7OLMe^L{;)Z)|~5s0B)avkDaS!G-3<_n{QH#o<8QFt8n6x5a!eoR3f_rpH$A-D+ zdTZqi;cA$NTJeKWrhe4$S*Y-O1!^n)ZrVdrEo(US?ojV1K`m%5#6ksYNl>uXLV5Y| zPy;)LNjQ^wD{O&xLWOG$|HuN3Pzv1wWx3noZuqciUqf=xcpIU{kHBrP!Ea~(e?>t~ z_FLE&z6#axGpMZz%?Rq9p$0k>%K7?3S!Ogm8g7C5z7@*k7eZO~O85x8(X{VmHG01r zc2WFaLO~s`f|~dyC==bL4)7jRe-LV=k3((MQ}7V@29&eC1=ar}Q~wgm7dp=h-uH&X zs1JmiZyqeDVKoJ5)C^_9v!Eur6l$e=&HJ0+TIxT8BVmu(fsaguvfwf(1x|#TpaE(j z&9DNV0;T9_hUd&?|4*QyNP|rK9@IdeLpe*2Ie|q6!6T>-fn(rwD23}G5otBU!{H53 zivPm!At*&3gL2A`pe$EOejfk_%q;{OO`$=1J;!hnltL?^6xnL(^`@SMQs7jmfxctj zUk|n7J7GU~FVu>kgBt%OC`I0Y8u!zJDOAo2H17>HaX+XJhC-QgjNw$Muv`SSw_Bhl zj6n^YfcoxasBzAO+QJK=EPIt{FBul@rJ#Wxg_`IYsPp_)D9zuPAGE&*ZQ8$tYPS~z zTQdr3q8h07=}_a;LRn}nlwuAX1T#?cT^PJCSeH?d(_9C~!rP!$^b*v7e}x_4`%otP z1Zsee3xoC^PwX%C)CHxJPiJyl0?se1tHq`hZLVX`vWLd|+N;s1Fttk}Fg*)JI_!e9Y zd-Km0xD66<)*bLh_z_gUA1$%05%3W>3ce4=!+}e=X2F$k0=ycIhR;IzPQ|hy%=^H? zku;2?AkF4MX}$>3*IEH(i9N6@{4vxX-U`+4NvM4B4Ah>#3Dy4-SPwfb$AO^-x5A5I zXZSAEe4i}G{%ZJ~hALROA~01i!=vFy+Q&kfdIRhP>!2n|nf8-S{Q}sZ_A4Oi-?|G< zf*(Kv%^JBf$o-9wgVTCwCHCJ&;R_nhgvYN6G<^|jrPEhi)@-;1Vs-0MsFl48=fI_F z=mXD%VfYZNfFDDx@KaO&0uG}dS{rP^2&jcmEl`jN=fSH8uZ{3SzWm2J?f|sEwVBHZ z{4S30Hr#|AE9tl3c+2`7T#oi*;n64Z9q*TK53b*HcLZL3ffFofFO-Epg*{-$NZ`bU zz7%9q8!B8z!ftRTR0dlLyTd4~h9^OEvo416oj0ITb44`piT+USHq^qVL9PPUN+<<( zn|d)|!Fr6sJYIB+1z#m{WTfi%OQ1e*;K?u!yTI3>4w?6$ChCMEDEIe<8n_0^ za?_ypb`jJ9RzvmM4tv3Gz#Z@c*n#=2cPVJ#4^4-z4S^zqpiDR!YTzZXGu#NJz;-B0 zH9?GMebcnR2sPeY=6yvxP^34MQ&&TcHwPBFP*_1hd%X$vglVYu)1fpz4=QC|2|L4^ zp>8^Nnf5236g>cC!4F^(Ry79Sw?cnw;7Ho{KrTbp{f*dP6MjKMSJo1n(K4@%*up}hY!D9ap$S=8@XD8&{RC@iHA zGYvOGt^84lpIH^DAd$qOER=%XVJobHyP+m38eR=2P`};O-+nPPz$&T%JlcZm*JC8 z6P1`<{eBH)i5H>9eH&IO{y(Q6O}pfRiFz7VL#=co>1T|hQ)M2*<%6D#p1;zc{6x8u4r~zJqN)&&C<6xJTz%o-{nEGO9 z!xnf5+yiB)%b`;8J}AW=fCJ%EP~-g_YO4?387OeXPVBF68$yF#jD|ApL@14CL79FT zJOZ8ob-w4JR&XKIcb7w)$+`yW`v;)H^9iW_&%<8uL#Te8T7!iSZ^iz45vD|1O;tDHPpnDgBR9xs1FxHt!x9-1oco8oMzg;4fWk+P!`z-_1$%*eLt+B zelHvY--VaJ0c?GZ;{R4;2@Nm9t#ItA+*aUjs6_G%91i!N7MuYu!Wq>2pB`LXHo+qG zAHeZ2Oxhd?cR=~Vw_#uSL#VCU4`sn8U`OV(o~Ez@{sHQPk!J>`p9?kdDyWq;L%lCR z4Y&u&GB?8vydRE*lg{F903E0;x*zKMN1-z5(@c04?~il)#Yq%Kk$^ZvHwXFx_{fU z2Ezhe3irX~@GTgFQ_n#OxEIcYufQpA__={8PlQ@w6js0l)Oa3LbX){0;WbcOa03iM zW@O*MCcnb3TSJ)z;BS;qM3f7#zI6pseq^!o)0^*x2QykR zi2nYwrl1$)UT~@Dq(7l!CF^SBXatK|KSA_tL7wtU{Fx3uYs&M?w~tc416fCX0X*8Y z_lL8Q2yMSc^b}^&P+>ZdEBsr|M(PT+aq7WyD)L{*2-;tRZzIQ0u7`IcGWh{S&oDEV z%0JUTJaqxA&!CdpUbrM^EBLXxno3t*EQB5+pU`t7(uwvbV1Hx`;v({a#mLVQgBt+%zdy5R_$5-$ zH=B{srb8O`G2_fJZDH!iP*$vyTKwlc{=FS}44IE;e(Oibbx0F(2%_gAv<=DwIg7`KNQxQ57l;)%G>dsG_X z7^M8{pxi>`&&WE{csZ=5{aE-b(|x5A;3(eRk9-FyY%wo>LuI}xQ?$CZD^H+4gZdQYpOimT2c9GnM{Yv& z--7itA`c>ik-oGIK#rrVXO8J}8RgUc7F^6WjgQl?966r)f5Xnm;pUyywfNGIfoo@^ zXRU8=?WF4@>~z9O*-0;!Pq?;|NO&z-zbO?@)!Sa3-zRHFyj+9b66c?c8;z&ktnH*? zcFN1S+3<{-^elhaEeyLZo=hiN?W~({qdD6#-R-)Jm$Y+CnTTg|8kS+)RF0m_aks^d zwGHcK_}0lp8~om0%C%d)yhgV-wKyq8WZGE9skh@fJLmbGVs18`VF-UAX)hbk#l2M6 z-s0u$C`)q^Sy=O^OPCfj3OWi{g|+snk(rKxq4f;CcB@zessE)~FPHTAszVa<=^H+UbREm}t*w!WLWY|RZ4jpq| zTCU(19n5lYq4RuCN=0S)sFzH#+Rtv(+XM@3T;s$ z1MAc6U1sTUrU_LaMEew z1W(ZfnINv5tli=!5^OgH%DBx8;*VJ!%ct25JUMHRbi?&wdzEi61=EUnHX0t~cUzxw zlD?CCWj5b3dco)_AGB$^Rr#u#$Y4{=xwieNoUFc zYh8a+qHgiIk-shO8+B1vHyh2w(^9!~%;;{RE`DxU;lXUBdS{b*ZT~njT49wmk9=!hEJLiDjq-i)DH5&;`}QY?Z>t_6Su4O5x8tbEWB1UJX?%8kVH2b>gag&RUn`@VC|l zTfN-lXethwy0>e)5$~OPcOf|Ybw;o&5trM7zmrZghmF5Aa&9kJp?~z~0EoCzN86|L z*x)q#=PRLb@bJfJl3{z9>!y{@l5szSa7g%moQ&5uadG<#RC zXdb`t6*Ws5T)b=cPYZq~(Ij4wdre^AqFSw!YAv5?b)N21YQ%xq-n7zHSG(O~KFvRpl7b+ao(>HI5*TFuf+#G(@R1V!NiNnvcdHyI`M}5Z2r-Qp5<{?nnUG7x!PU-1~g_9l^94?qSY_CqZI;5E==a8WMbmYX? zQd}m8#p1$w<4P0ey%Q>qtKHgdxs$5TlO(3usYLNxwc!G1Z7nxb$4TVkjj`aE4=$&) zHRb$MJH;iZS+`cxi)xa%VRzkhjtc)rMNSP8O_JL|BHq{(96q{N_*YX`>6U)MH~wfb z-A)UQ+)vfWp%ihO_+PmX1;Trm=Qfe_oJ`jSW~}G#nj#j;!_X(2kQ?izdT|f48}kYm zUH+tzJX~+fx(D}!rLNt?f;_L#gjyMNkaA`bS`Vvn6KuTO?78GMHO2TqBbg=qhw0Eq zcS3He8Zn=Wv!t&~jzZaJLnhv+v}G62H0iMFaM!sBmeQsKUf`tsHww72RqdFEOGt|q z>`t4)%?T=BvrwDS1BKeQV;NbTYioHk3hbbi#ctdf{7WoaaJ}Vb!(pxL!5Ds?#@lLT zVi~TH(*z|5-*z@aVZ9)zW2{gYrWBsQ^|ou9xd{zcX-vpsn+trSRmb>=@t?kLH-*1^ zwAbVWdXt-I!I@Jze_HNe{un6Fk)!Qnmszf?>t8PM##KpDTHAiOsUdcjyH<+D%Q0eh zQ=WiL**YCSu+-w}RG&gq+}%Zs{GK}>ds^>CGI>r!F1*an|H~d$zUU?}YC;=Zp1YkD zq`!ZMX!}TNF$kBqwvdb9?VK&xeQu)Q&mv2ezwkpf=DG=8t2o5mr1V!2>eolPqnjG* z`|hqhrpJZz2gfk?X?79kY4q|fM5F>zSv=YhZ^RT~dy(tbjV<_2l8<0k+?HWR?(+0w zU=>~C^$L%#??CI2=ps zFTTAZd}R5MQQni;Cz4S(PU4NFo-6l<25)ld&*F9w-ejF%^YZ*m(FP{G`ufs?tF8%+ z;$t#EutV&*S#xmZ4b%(r%ivOc&A3oshRQZ_u6z6d^RG#`cHAvqxc0M38HBs;sq22# zZ5~(QasnyUuAdXCT9RUzjQ*&QEuOLA2a|LU)o&W54s8Y|+lBt-{u`)N@BZ@Uwp%h0 zU+TZ{%h1wV5~hER&3Rrz7HV;#-1N8uGMax$j=0>bbZuPhMq~lGvPrqVN7uVe9+5J; z*l+WoV}mR4|5=quo3E(oyNqAR1aWyIf+IFtdUESIp$Xb8-+BDoaI=HYDtpir@kj&2 zElwOXa3zkXoN#f=wjG7Ve1=I9^v7v&Lxl?;=^ji*J$Pm2R~_qR*+Fh*t?Vp0!Jnp{ zTduN$$?-w1F?Zx3D*nSIIjXC8`&;t=>yoTJ)%{p%mXlE`T)JzU6Y9{wv0UtN;_IDO z>vxfxEq;9Bu*%??SUPfh&(LJtOE=+7+T9jBRAF=NCGl7Sp<^ve zaM3nbVm8UEFFxnq)aBr~XVyJmXuESX#NCXilwfMQ?DS7J=Vt%B=_ zzg;Fw359>VaWuFQ{s^en2y!Q=O7a6wkkx7UgMs!`gm$nIdPmTY0}61o@S={T&SDWW@%!btuf8(jK*#q$xr%ANK&a)f7SDU*bFW{oIFs7r<8P9r94`(S`M3X{xZ?vn~VU~8G$-F=!3N8 zrlwg-gIke4H{F}P1cR!R$sO5)t|mLPEKHp6DoA)&q}~h_WJ%@Gc6!!pJU@D!gf7UO zX>Hp1LCccL+P1AaEM@$`{Li@<``0Q)(wW@u5YZoI{J*te_*A@x)gO!nd!_3p+wR6_ VCF78?B5s3!$H|0CXQYRP{s(_8RB!+Q delta 7355 zcmYk>3w+PjAII_Yn_ZZhF_*b-%nV~}#5+gAhbzgJ5nej~`nJ}Dd8!W-9l$YD`8r1cz zwtk284SW3nYDquE{&)&QF{QOJF_?k6J{Y5L1nNO=MZcbWKAEbx3{|eg9DEYh(OG1# z%+IJN3ToqZ7==0}jZy77qMk4vwSu`=4Tqxc8;jb)X{Z&M*M{}ij22O$87{XC)}e0L zhU0J#Y67j>8dDdq!&n@IdXj0V2`ofS;C|EttwQy`9yQ>LsFi#L)qZbV)?W<|*anAD zdwmQwf&XDR1}Awp)I`(fyk_drb`*OqU@Y|0~S{W{dZE~?+1elqHCpKWm1 zUib#nss9o6!+}_idcxPRI_|Z8fDx3BqgLXKt^X4fDEmX&dkvCM zPmqCHkzUq3)M+h5bzEdE!EThN;%&GE^)+ji>^<>l)Py$TBHU!lX&t?N|@@qb6_ywRER!`5bCO7qBM&gS>-GWJmA5_83Vy8*AVVwmjN86|3p{ zf46P06gALt)Jm)lG%#j^EpJ6V(GJuW?7}Me5o*OgL7ny!wtN<~#}{n*Z){09G{u`x z61LR$Ka-3O(BL0B2uuiHsU;^q1J75rY$G{d^^Y9kx3sEcf zJl4it=-1&mL`F~k1=h!t*cLCLzHY5}Z)#%QtXZgu`SV~NMNQxZ)Rw(s z-GiFIJE(DwbYlHg@r|uGk9y)usE)$Zyc-fwTato$qh+E7C`3(QII6>P>ul777oqyU z4>ghHsFix$x+#tI*HXShh4$(_RENhSl|CiWHiGmn1{1aPx=OG=?`HOJdSGj zC#s_>sI7};R%#!I}4z&V(P)j)#wKell z11z=mD{T20WKqn^$QQ=^hWcgGx~KO>orDW0??+7}pNo2sjYw1T7W%nnLbJS|Sh?7q z@_f{b;;>P%CsAWAG=efmI85 zH())~UQa~5*cPC+aFwlpvcT`n{8cLWCYeL1fvOGg%5|*;$itaMs0kdvNIZ@@gx{l9 zrq)33uVEK#PI(K~!;et?p2bkSh}x3NelmK3n+AD@Z6xX}Oho;0xeYb*J5cQ$ybB*g ztw4jp-YdEVYJd#Xn=>1Ac#Bc}m7%t(0yXh@SR4Hhk{Ly29cr&bShu zV?R`fBT*fep$49bV{oo5pF;KX3r1ns4c@>ps6*Hac>ur3CZoL@fVFUfcfrg?O<)1m z#7fkFPob7{tF3<5N>EGhN3GCfsJ-5ZI+R;b;U%a;yb|l2`8Z@mVxT859(`{kLs_`UN6S$DNn)qxUGow z??xt_?*hAEW}!Mbh%@m+R7bhPyeG*=eG5k7bR3VG;BnMSox`T+8}4mUENaVIqxwlj zouv%aeSL?s{_$jnQlTaDqh?%*TH5ufj$gLd-$!lHcc_kjMXgkoTfB+YM0H%>nuvO! z4AfS1M@?iPYQ=B#+f1=-P=*>{4r)p7#bjKGn#cj{h$pZi)*9groP?TiC)E9YkpGz> zd}zzIp(cD9)$i}9_Wsb3-n+gbszDP}2knrDGnuF-ti%{xi)!~OYAX(66Z{z4;RTGv z*iqgo?}b`{Y}6Yu4>f^uY|QxPPBQ9X1?p?{5^BKRsISjKRQ+Mpl6{Vv;Azy7{)XDR z&|+^znxgK{K;4&(O|bxVe>rO9ZpYgC{yVn82GkSn3tZs0AZh|%p*lQ`8u(Y#3YgKJ zQK$*Tq7GX+*2OH;irtKw=v35_&qv)~i6Vy3d*z|nm-15N)nPuy0!*I3zcFwQCSY+X=K~j)vi@Dk?4cqH zub_ij6TQ9r1nW`$3AMzble`sbjGAB^=3^_=Ue83mKbD~eT7`Omz4rP+RDY*XD{$FQ zW*V8uGVk~NTpUSxGgec5xz|Aq>ctX=8XyIAy(hN9Jk!w0-oY*yL1Uer-l!+;i$ORT zb^j35p}h@5@m^#_{pKMu9C{PN#}LdU3W$4%j|im;#2})t3MBnz{0UbCO5TfSE%`>o z2I6_5I&FT%t7)grw5DD!Hl-du_CL?do6e|}(CpqI{veJL4Y=Vm{5Mg)jzSnJ-A*JD zT0Ny+gwDb`LWfi-$HO$_9AyV4^EG^Gyo; zr#LXRC@;XO*ow#`KB3%07fET9U-Po&F?@+QXUi{JpTk(6-oK=~0-xT$-xiUtMh6+h zSLACD3yBKiOJXshlm9cZg_uS}(zXbj;B4$iT$?z<=2csfg6Rauj>Pyqx#=R=B}5gX z1LclbNpvGxP*y4>ZX)6+Kcx!N>%?>-in`r+ZQ_d*_$T@qTR8{Y6WfW$iF(}gU+?)T zkxD$wL-+)7h1f(qNhr?QGsrwj)roz?H$+`R=>QQJ zzdns>QfNS2Pbe)ViizdK4nnCRF@UH==&gAtkw!d1R3+-t&w6x-?!?(&RFFZ?KE^#l>iBLM} z5%_GuXW(?>P~s2~P4poq5)Tt!>xF-w%nQWT^Z}W8;(7+@OvDhYDW4#!kdG(&lMf-3 zrVvjPn^myMeLX%Vyzbbsu>~_{Oe>vHdh2A Date: Thu, 18 Mar 2021 11:53:32 +0100 Subject: [PATCH 84/96] updated external image viewer --- cookbook/static/vue/js/recipe_view.js | 2 +- vue/src/apps/RecipeView/RecipeView.vue | 2 +- vue/src/components/ImageViewer.vue | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cookbook/static/vue/js/recipe_view.js b/cookbook/static/vue/js/recipe_view.js index 2f5efe25..264ca87d 100644 --- a/cookbook/static/vue/js/recipe_view.js +++ b/cookbook/static/vue/js/recipe_view.js @@ -1 +1 @@ -(function(e){function t(t){for(var i,r,o=t[0],c=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),o=s("5f5b"),c=(s("2dd8"),s("bc3a")),l=s.n(c),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},b=[],g=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,g,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.number))}})},E=[],T={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},$=T,P=Object(C["a"])($,S,E,!1,null,null,null),M=P.exports,z={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:M},template:"
".concat(this.code,"
")})}},N=z,D=Object(C["a"])(N,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),H=s.n(U);i["default"].prototype.moment=H.a;var I={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=H()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=H()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},A=I,L=Object(C["a"])(A,v,b,!1,null,null,null),B=L.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:H()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,oe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("img",{attrs:{src:e.pdfUrl,width:"100%",height:"700px",alt:e._("External Recipe Image")}})])},ce=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,oe,ce,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.calories))}}),e._v(" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.fats))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.proteins))}}),e._v(" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,be=Object(C["a"])(ve,ue,me,!1,null,null,null),ge=be.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,Te=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),$e=Te.exports,Pe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Me=[],ze=s("8e5f"),Ne=s.n(ze);i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Ne.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,Pe,Me,!1,null,null,null)),He=Ue.exports;i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var Ie={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:B,RecipeContextMenu:ee,Nutrition:ge,Keywords:we,LoadingSpinner:$e,AddRecipeToBook:He},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var o,c=Object(r["a"])(n.ingredients);try{for(c.s();!(o=c.n()).done;){var l=o.value;t.$set(l,"checked",!1)}}catch(d){c.e(d)}finally{c.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=H()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var o=i.value;o.id===e.id&&this.$set(o,"checked",!o.checked)}}catch(c){n.e(c)}finally{n.f()}}}catch(c){s.e(c)}finally{s.f()}}}},Ae=Ie,Le=Object(C["a"])(Ae,a,n,!1,null,null,null),Be=Le.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Be)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return o})),s.d(t,"e",(function(){return c})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var o=(i+n)/(a+r);if(e===o){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var c=Math.floor(i/a);return[c,i-c*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var o={methods:{_:function(e){return c(e)}}};function c(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("use_fractions")){var s="",i=a(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file +(function(e){function t(t){for(var i,r,o=t[0],c=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")||e.recipe.file_path.includes(".gif")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),o=s("5f5b"),c=(s("2dd8"),s("bc3a")),l=s.n(c),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},b=[],g=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,g,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.number))}})},E=[],T={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},$=T,P=Object(C["a"])($,S,E,!1,null,null,null),M=P.exports,z={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:M},template:"
".concat(this.code,"
")})}},N=z,D=Object(C["a"])(N,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),H=s.n(U);i["default"].prototype.moment=H.a;var I={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=H()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=H()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},A=I,L=Object(C["a"])(A,v,b,!1,null,null,null),B=L.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:H()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,oe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticStyle:{"text-align":"center"}},[s("b-img",{attrs:{src:e.pdfUrl,alt:e._("External Recipe Image")}})],1)},ce=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,oe,ce,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.calories))}}),e._v(" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.fats))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.proteins))}}),e._v(" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,be=Object(C["a"])(ve,ue,me,!1,null,null,null),ge=be.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,Te=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),$e=Te.exports,Pe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Me=[],ze=s("8e5f"),Ne=s.n(ze);i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Ne.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,Pe,Me,!1,null,null,null)),He=Ue.exports;i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var Ie={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:B,RecipeContextMenu:ee,Nutrition:ge,Keywords:we,LoadingSpinner:$e,AddRecipeToBook:He},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var o,c=Object(r["a"])(n.ingredients);try{for(c.s();!(o=c.n()).done;){var l=o.value;t.$set(l,"checked",!1)}}catch(d){c.e(d)}finally{c.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=H()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var o=i.value;o.id===e.id&&this.$set(o,"checked",!o.checked)}}catch(c){n.e(c)}finally{n.f()}}}catch(c){s.e(c)}finally{s.f()}}}},Ae=Ie,Le=Object(C["a"])(Ae,a,n,!1,null,null,null),Be=Le.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Be)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return o})),s.d(t,"e",(function(){return c})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var o=(i+n)/(a+r);if(e===o){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var c=Math.floor(i/a);return[c,i-c*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var o={methods:{_:function(e){return c(e)}}};function c(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("use_fractions")){var s="",i=a(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file diff --git a/vue/src/apps/RecipeView/RecipeView.vue b/vue/src/apps/RecipeView/RecipeView.vue index 43cd0a16..8ea41ee8 100644 --- a/vue/src/apps/RecipeView/RecipeView.vue +++ b/vue/src/apps/RecipeView/RecipeView.vue @@ -122,7 +122,7 @@
+ v-if="recipe.file_path.includes('.png') || recipe.file_path.includes('.jpg') || recipe.file_path.includes('.jpeg') || recipe.file_path.includes('.gif')">
diff --git a/vue/src/components/ImageViewer.vue b/vue/src/components/ImageViewer.vue index 274933b0..a01c35ee 100644 --- a/vue/src/components/ImageViewer.vue +++ b/vue/src/components/ImageViewer.vue @@ -1,7 +1,7 @@ From e00b6b92931ba40b8c924415caa940e61af52530 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 11:56:47 +0100 Subject: [PATCH 85/96] fixed meal plan creation from recipe context menu --- cookbook/static/vue/js/recipe_view.js | 2 +- vue/src/components/RecipeContextMenu.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook/static/vue/js/recipe_view.js b/cookbook/static/vue/js/recipe_view.js index 264ca87d..84307478 100644 --- a/cookbook/static/vue/js/recipe_view.js +++ b/cookbook/static/vue/js/recipe_view.js @@ -1 +1 @@ -(function(e){function t(t){for(var i,r,o=t[0],c=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")||e.recipe.file_path.includes(".gif")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),o=s("5f5b"),c=(s("2dd8"),s("bc3a")),l=s.n(c),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},b=[],g=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,g,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.number))}})},E=[],T={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},$=T,P=Object(C["a"])($,S,E,!1,null,null,null),M=P.exports,z={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:M},template:"
".concat(this.code,"
")})}},N=z,D=Object(C["a"])(N,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),H=s.n(U);i["default"].prototype.moment=H.a;var I={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=H()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=H()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},A=I,L=Object(C["a"])(A,v,b,!1,null,null,null),B=L.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:H()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,oe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticStyle:{"text-align":"center"}},[s("b-img",{attrs:{src:e.pdfUrl,alt:e._("External Recipe Image")}})],1)},ce=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,oe,ce,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.calories))}}),e._v(" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.fats))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.proteins))}}),e._v(" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,be=Object(C["a"])(ve,ue,me,!1,null,null,null),ge=be.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,Te=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),$e=Te.exports,Pe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Me=[],ze=s("8e5f"),Ne=s.n(ze);i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Ne.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,Pe,Me,!1,null,null,null)),He=Ue.exports;i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var Ie={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:B,RecipeContextMenu:ee,Nutrition:ge,Keywords:we,LoadingSpinner:$e,AddRecipeToBook:He},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var o,c=Object(r["a"])(n.ingredients);try{for(c.s();!(o=c.n()).done;){var l=o.value;t.$set(l,"checked",!1)}}catch(d){c.e(d)}finally{c.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=H()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var o=i.value;o.id===e.id&&this.$set(o,"checked",!o.checked)}}catch(c){n.e(c)}finally{n.f()}}}catch(c){s.e(c)}finally{s.f()}}}},Ae=Ie,Le=Object(C["a"])(Ae,a,n,!1,null,null,null),Be=Le.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Be)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return o})),s.d(t,"e",(function(){return c})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var o=(i+n)/(a+r);if(e===o){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var c=Math.floor(i/a);return[c,i-c*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var o={methods:{_:function(e){return c(e)}}};function c(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("use_fractions")){var s="",i=a(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file +(function(e){function t(t){for(var i,r,o=t[0],c=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")||e.recipe.file_path.includes(".gif")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),o=s("5f5b"),c=(s("2dd8"),s("bc3a")),l=s.n(c),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},b=[],g=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,g,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.number))}})},E=[],T={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},$=T,P=Object(C["a"])($,S,E,!1,null,null,null),M=P.exports,z={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:M},template:"
".concat(this.code,"
")})}},N=z,D=Object(C["a"])(N,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),H=s.n(U);i["default"].prototype.moment=H.a;var I={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=H()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=H()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},A=I,L=Object(C["a"])(A,v,b,!1,null,null,null),B=L.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?recipe="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:H()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,oe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticStyle:{"text-align":"center"}},[s("b-img",{attrs:{src:e.pdfUrl,alt:e._("External Recipe Image")}})],1)},ce=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,oe,ce,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.calories))}}),e._v(" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.fats))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.proteins))}}),e._v(" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,be=Object(C["a"])(ve,ue,me,!1,null,null,null),ge=be.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,Te=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),$e=Te.exports,Pe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Me=[],ze=s("8e5f"),Ne=s.n(ze);i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Ne.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,Pe,Me,!1,null,null,null)),He=Ue.exports;i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var Ie={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:B,RecipeContextMenu:ee,Nutrition:ge,Keywords:we,LoadingSpinner:$e,AddRecipeToBook:He},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var o,c=Object(r["a"])(n.ingredients);try{for(c.s();!(o=c.n()).done;){var l=o.value;t.$set(l,"checked",!1)}}catch(d){c.e(d)}finally{c.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=H()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var o=i.value;o.id===e.id&&this.$set(o,"checked",!o.checked)}}catch(c){n.e(c)}finally{n.f()}}}catch(c){s.e(c)}finally{s.f()}}}},Ae=Ie,Le=Object(C["a"])(Ae,a,n,!1,null,null,null),Be=Le.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Be)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return o})),s.d(t,"e",(function(){return c})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var o=(i+n)/(a+r);if(e===o){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var c=Math.floor(i/a);return[c,i-c*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var o={methods:{_:function(e){return c(e)}}};function c(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("use_fractions")){var s="",i=a(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file diff --git a/vue/src/components/RecipeContextMenu.vue b/vue/src/components/RecipeContextMenu.vue index 5c91fe1c..19bb6416 100644 --- a/vue/src/components/RecipeContextMenu.vue +++ b/vue/src/components/RecipeContextMenu.vue @@ -24,7 +24,7 @@ {{ _('Add to Shopping') }}
- {{ _('Add to Plan') }} From 780c9291621644973b60445d2d9f169f4b9a7916 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 12:07:02 +0100 Subject: [PATCH 86/96] fixed url import space --- cookbook/views/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 862e60aa..da307b8c 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -543,7 +543,7 @@ def recipe_from_url(request): }, status=400 ) - return get_from_html(response.text, url) + return get_from_html(response.text, url, request.space) @group_required('user') From 3c1b6a5f3a95bcd9e9ca1deaa995a820f6ae5ee2 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 12:08:12 +0100 Subject: [PATCH 87/96] updated unraid docs image --- docs/install/unraid.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/install/unraid.md b/docs/install/unraid.md index daf3de17..3babcdc6 100644 --- a/docs/install/unraid.md +++ b/docs/install/unraid.md @@ -15,7 +15,7 @@ You will first need to install Community Applications (CA) by following the dire https://forums.unraid.net/topic/38582-plug-in-community-applications/ After that, you can go to the "Apps" tab in unRAID and search for Recipes and locate the Recipes container and install it. -![image](https://user-images.githubusercontent.com/724777/97094837-bc616580-1626-11eb-9ec1-79ff034fe8d4.png) +![image](https://user-images.githubusercontent.com/724777/111038251-faa0cb00-83f5-11eb-9807-37815de8d795.png) The default settings should by fine for most users, just be sure to enter a secret key that is randomly generated. Then chooose apply. @@ -24,4 +24,4 @@ Then chooose apply. After the container installs, click on the Recipes icon and click the WebUI button to launch the web user interface. Set the container to auto-start if you wish. -![image](https://user-images.githubusercontent.com/724777/97094892-4c9faa80-1627-11eb-9eae-d32d0f35b36f.png) +![image](https://user-images.githubusercontent.com/724777/111038276-16a46c80-83f6-11eb-866b-b3bc9a2efb87.png) From 48c90c483ac6bb4f3a708f98a675139331591679 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 12:36:00 +0100 Subject: [PATCH 88/96] merged PR 474 adding manual json import --- cookbook/helper/recipe_url_import.py | 1 + cookbook/templates/url_import.html | 30 +++++++++++++++++++++++++++- cookbook/urls.py | 1 + cookbook/views/api.py | 21 +++++++++++++++++-- 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/cookbook/helper/recipe_url_import.py b/cookbook/helper/recipe_url_import.py index b2bb5338..959545c2 100644 --- a/cookbook/helper/recipe_url_import.py +++ b/cookbook/helper/recipe_url_import.py @@ -84,6 +84,7 @@ def find_recipe_json(ld_json, url, space): for x in ld_json['recipeIngredient']: if x.replace(' ', '') != '': + x = x.replace('½', "0.5").replace('¼', "0.25").replace('¾', "0.75") try: amount, unit, ingredient, note = parse_ingredient(x) if ingredient: diff --git a/cookbook/templates/url_import.html b/cookbook/templates/url_import.html index 0fdc8114..0481e7d1 100644 --- a/cookbook/templates/url_import.html +++ b/cookbook/templates/url_import.html @@ -30,6 +30,19 @@
+
+
+
+ +
+ +
+
+
+
+
@@ -322,6 +335,21 @@ this.makeToast(gettext('Error'), gettext('There was an error loading a resource!') + err.bodyText, 'danger') }) }, + loadRecipeJson: function () { + this.recipe_data = undefined + this.error = undefined + this.loading = true + this.$http.post("{% url 'api_recipe_from_json' %}", {'json': this.json_data}, {emulateJSON: true}).then((response) => { + console.log(response.data) + this.recipe_data = response.data; + this.loading = false + }).catch((err) => { + this.error = err.data + this.loading = false + console.log(err) + this.makeToast(gettext('Error'), gettext('There was an error loading a resource!') + err.bodyText, 'danger') + }) + }, importRecipe: function () { if (this.importing_recipe) { this.makeToast(gettext('Error'), gettext('Already importing the selected recipe, please wait!'), 'danger') @@ -361,7 +389,7 @@ this.recipe_data.recipeIngredient[index] = new_unit }, addKeyword: function (tag) { - let new_keyword = {'text':tag,'id':null} + let new_keyword = {'text': tag, 'id': null} this.recipe_data.keywords.push(new_keyword) }, openUnitSelect: function (id) { diff --git a/cookbook/urls.py b/cookbook/urls.py index 4f055703..cc562653 100644 --- a/cookbook/urls.py +++ b/cookbook/urls.py @@ -91,6 +91,7 @@ urlpatterns = [ path('api/log_cooking//', api.log_cooking, name='api_log_cooking'), path('api/plan-ical///', api.get_plan_ical, name='api_get_plan_ical'), path('api/recipe-from-url/', api.recipe_from_url, name='api_recipe_from_url'), + path('api/recipe-from-json/', api.recipe_from_json, name='api_recipe_from_json'), path('api/ingredient-from-string/', api.ingredient_from_string, name='api_ingredient_from_string'), path('dal/keyword/', dal.KeywordAutocomplete.as_view(), name='dal_keyword'), diff --git a/cookbook/views/api.py b/cookbook/views/api.py index da307b8c..3db33066 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -27,7 +27,7 @@ from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest, CustomIsOwner, CustomIsShare, CustomIsShared, CustomIsUser, group_required) -from cookbook.helper.recipe_url_import import get_from_html +from cookbook.helper.recipe_url_import import get_from_html, find_recipe_json from cookbook.models import (CookLog, Food, Ingredient, Keyword, MealPlan, MealType, Recipe, RecipeBook, ShoppingList, ShoppingListEntry, ShoppingListRecipe, Step, @@ -337,7 +337,7 @@ class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin): class ShoppingListRecipeViewSet(viewsets.ModelViewSet): queryset = ShoppingListRecipe.objects serializer_class = ShoppingListRecipeSerializer - permission_classes = [CustomIsOwner| CustomIsShared ] + permission_classes = [CustomIsOwner | CustomIsShared] def get_queryset(self): return self.queryset.filter(Q(shoppinglist__created_by=self.request.user) | Q(shoppinglist__shared=self.request.user)).filter(shoppinglist__space=self.request.space).all() @@ -546,6 +546,23 @@ def recipe_from_url(request): return get_from_html(response.text, url, request.space) +@group_required('user') +def recipe_from_json(request): + mjson = request.POST['json'] + + md_json = json.loads(mjson) + if ('@type' in md_json + and md_json['@type'] == 'Recipe'): + return JsonResponse(find_recipe_json(md_json, '', request.space)) + return JsonResponse( + { + 'error': True, + 'msg': _('Could not parse correctly...') + }, + status=400 + ) + + @group_required('user') def ingredient_from_string(request): text = request.POST['text'] From fe1ddf12376548acee2bba28b98447dd50eb0bae Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 14:43:19 +0100 Subject: [PATCH 89/96] improved paprika importer --- cookbook/integration/integration.py | 2 +- cookbook/integration/paprika.py | 53 ++++++++++++----------------- docs/features/import_export.md | 38 +++++++++++---------- 3 files changed, 42 insertions(+), 51 deletions(-) diff --git a/cookbook/integration/integration.py b/cookbook/integration/integration.py index 49200d54..08ad6ad2 100644 --- a/cookbook/integration/integration.py +++ b/cookbook/integration/integration.py @@ -84,7 +84,7 @@ class Integration: try: self.files = files for f in files: - if '.zip' in f.name: + if '.zip' in f.name or '.paprikarecipes' in f.name: import_zip = ZipFile(f.file) for z in import_zip.filelist: if self.import_file_name_filter(z): diff --git a/cookbook/integration/paprika.py b/cookbook/integration/paprika.py index 596b0ba2..26fd6b86 100644 --- a/cookbook/integration/paprika.py +++ b/cookbook/integration/paprika.py @@ -1,3 +1,4 @@ +import base64 import json import re from io import BytesIO @@ -6,51 +7,39 @@ from zipfile import ZipFile import microdata from bs4 import BeautifulSoup +from cookbook.helper.ingredient_parser import parse from cookbook.helper.recipe_url_import import find_recipe_json from cookbook.integration.integration import Integration from cookbook.models import Recipe, Step, Food, Ingredient, Unit +import gzip class Paprika(Integration): - def import_file_name_filter(self, zip_info_object): - print("testing", zip_info_object.filename) - return re.match(r'^Recipes/([A-Za-z\s])+.html$', zip_info_object.filename) - def get_file_from_recipe(self, recipe): raise NotImplementedError('Method not implemented in storage integration') def get_recipe_from_file(self, file): - html_text = file.getvalue().decode("utf-8") + with gzip.open(file, 'r') as recipe_zip: + recipe_json = json.loads(recipe_zip.read().decode("utf-8")) - items = microdata.get_items(html_text) - for i in items: - md_json = json.loads(i.json()) - if 'schema.org/Recipe' in str(md_json['type']): - recipe_json = find_recipe_json(md_json['properties'], '', space=self.request.space) - recipe = Recipe.objects.create(name=recipe_json['name'].strip(), created_by=self.request.user, internal=True, space=self.request.space) - step = Step.objects.create( - instruction=recipe_json['recipeInstructions'] - ) + recipe = Recipe.objects.create( + name=recipe_json['name'].strip(), description=recipe_json['description'].strip(), + created_by=self.request.user, internal=True, space=self.request.space) - for ingredient in recipe_json['recipeIngredient']: - f, created = Food.objects.get_or_create(name=ingredient['ingredient']['text'], space=self.request.space) - u, created = Unit.objects.get_or_create(name=ingredient['unit']['text'], space=self.request.space) - step.ingredients.add(Ingredient.objects.create( - food=f, unit=u, amount=ingredient['amount'], note=ingredient['note'] - )) + step = Step.objects.create( + instruction=recipe_json['directions'] + '\n\n' + recipe_json['nutritional_info'] + ) - recipe.steps.add(step) + for ingredient in recipe_json['ingredients'].split('\n'): + amount, unit, ingredient, note = parse(ingredient) + f, created = Food.objects.get_or_create(name=ingredient, space=self.request.space) + u, created = Unit.objects.get_or_create(name=unit, space=self.request.space) + step.ingredients.add(Ingredient.objects.create( + food=f, unit=u, amount=amount, note=note + )) - soup = BeautifulSoup(html_text, "html.parser") - image = soup.find('img') - image_name = image.attrs['src'].strip().replace('Images/', '') + recipe.steps.add(step) - for f in self.files: - if '.zip' in f.name: - import_zip = ZipFile(f.file) - for z in import_zip.filelist: - if re.match(f'^Recipes/Images/{image_name}$', z.filename): - self.import_recipe_image(recipe, BytesIO(import_zip.read(z.filename))) - - return recipe + self.import_recipe_image(recipe, BytesIO(base64.b64decode(recipe_json['photo_data']))) + return recipe diff --git a/docs/features/import_export.md b/docs/features/import_export.md index 069687eb..2c9f786b 100644 --- a/docs/features/import_export.md +++ b/docs/features/import_export.md @@ -1,6 +1,10 @@ This application features a very versatile import and export feature in order to offer the best experience possible and allow you to freely choose where your data goes. +!!! warning "WIP" + The Module is relatively new. There is a know issue with [Timeouts](https://github.com/vabene1111/recipes/issues/417) on large exports. + A fix is being developed and will likely be released with the next version. + The Module is build with maximum flexibility and expandability in mind and allows to easily add new integrations to allow you to both import and export your recipes into whatever format you desire. @@ -14,6 +18,19 @@ if your favorite one is missing. Because of this importing as many formats as possible is prioritized over exporting. Exporter for the different formats will follow over time. +Overview of the capabilities of the different integrations. + +| Integration | Import | Export | Images | +| ----------- | ------ | ------ | ------ | +| Default | ✔️ | ✔️ | ✔️ | +| Nextcloud | ✔️ | ⌚ | ✔️ | +| Mealie | ✔️ | ⌚ | ✔️ | +| Chowdown | ✔️ | ⌚ | ✔️ | +| Safron | ✔️ | ⌚ | ❌ | +| Paprika | ✔️ | ⌚ | ✔️ | + +✔ = implemented, ❌ = not implemented and not possible, ⌚ = not yet implemented + ## Default The default integration is the build in (and preferred) way to import and export recipes. It is maintained with new fields added and contains all data to transfer your recipes from one installation to another. @@ -88,22 +105,7 @@ Then simply upload the entire `.zip` file to the importer. Safron exports do not contain any images. They will be lost during import. ## Paprika -Paprika can create two types of export. The first is a proprietary `.paprikarecipes` file in some kind of binarized format. -The second one is HTML files containing at least a bit of microdata. +A Paprika export contains a folder with a html representation of your recipes and a `.paprikarecipes` file. -If you want to import your Paprika recipes follow these steps - -1. create a html export -2. Create a `.zip` file from the `Recipes` folder (next to the `index.html`) the structure should look like this -``` -Recipes.zip/ - └── Recipes/ - ├── recipe one.html - ├── recipe two.thml - └── Images/ - ├── 5D5E09CD-8F88-4F61-8121-0727DD3E0E89/ - │ └── 5D5E09CD-8F88-4F61-8121-0727DD3E0E89.jpg - └── 7CEE2AC6-DF60-4464-9B61-4F5E347EB90C/ - └── 7CEE2AC6-DF60-4464-9B61-4F5E347EB90C.jpg -``` -3. Upload the zip file in the import module and import it \ No newline at end of file +The `.paprikarecipes` file is basically just a zip with gzipped contents. Simply upload the whole file and import +all your recipes. \ No newline at end of file From 906da253013c55c9046ef777272b93420429a926 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 17:02:02 +0100 Subject: [PATCH 90/96] prevent duplicate imports --- cookbook/integration/integration.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/cookbook/integration/integration.py b/cookbook/integration/integration.py index 08ad6ad2..2cbbf02a 100644 --- a/cookbook/integration/integration.py +++ b/cookbook/integration/integration.py @@ -10,7 +10,7 @@ from django.http import HttpResponseRedirect, HttpResponse from django.urls import reverse from django.utils.formats import date_format from django.utils.translation import gettext as _ -from cookbook.models import Keyword +from cookbook.models import Keyword, Recipe class Integration: @@ -81,6 +81,7 @@ class Integration: :param files: List of in memory files :return: HttpResponseRedirect to the recipe search showing all imported recipes """ + ignored_recipes = [] try: self.files = files for f in files: @@ -90,15 +91,32 @@ class Integration: if self.import_file_name_filter(z): recipe = self.get_recipe_from_file(BytesIO(import_zip.read(z.filename))) recipe.keywords.add(self.keyword) + if duplicate := self.is_duplicate(recipe): + ignored_recipes.append(duplicate) import_zip.close() else: recipe = self.get_recipe_from_file(f.file) recipe.keywords.add(self.keyword) + if duplicate := self.is_duplicate(recipe): + ignored_recipes.append(duplicate) except BadZipFile: messages.add_message(self.request, messages.ERROR, _('Importer expected a .zip file. Did you choose the correct importer type for your data ?')) + if len(ignored_recipes) > 0: + messages.add_message(self.request, messages.WARNING, _('The following recipes were ignored because they already existed:') + ' ' + ', '.join(ignored_recipes)) return HttpResponseRedirect(reverse('view_search') + '?keywords=' + str(self.keyword.pk)) + def is_duplicate(self, recipe): + """ + Checks if a recipe is already present, if so deletes it + :param recipe: Recipe object + """ + if Recipe.objects.filter(space=self.request.space, name=recipe.name).exists(): + recipe.delete() + return recipe.name + else: + return None + @staticmethod def import_recipe_image(recipe, image_file): """ From af1bc19fd86564c005659c4d732676b76e783dc9 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 18:08:22 +0100 Subject: [PATCH 91/96] fixed importer threading stuff --- cookbook/integration/chowdown.py | 4 +- cookbook/integration/integration.py | 51 ++++++++++++---------- cookbook/integration/mealie.py | 4 +- cookbook/integration/nextcloud_cookbook.py | 4 +- cookbook/models.py | 14 ++++++ cookbook/views/import_export.py | 12 ++++- 6 files changed, 58 insertions(+), 31 deletions(-) diff --git a/cookbook/integration/chowdown.py b/cookbook/integration/chowdown.py index 8ce74189..b0066327 100644 --- a/cookbook/integration/chowdown.py +++ b/cookbook/integration/chowdown.py @@ -67,8 +67,8 @@ class Chowdown(Integration): recipe.steps.add(step) for f in self.files: - if '.zip' in f.name: - import_zip = ZipFile(f.file) + if '.zip' in f['name']: + import_zip = ZipFile(f['file']) for z in import_zip.filelist: if re.match(f'^images/{image}$', z.filename): self.import_recipe_image(recipe, BytesIO(import_zip.read(z.filename))) diff --git a/cookbook/integration/integration.py b/cookbook/integration/integration.py index 2cbbf02a..db543ac1 100644 --- a/cookbook/integration/integration.py +++ b/cookbook/integration/integration.py @@ -10,6 +10,8 @@ from django.http import HttpResponseRedirect, HttpResponse from django.urls import reverse from django.utils.formats import date_format from django.utils.translation import gettext as _ +from django_scopes import scope + from cookbook.models import Keyword, Recipe @@ -81,37 +83,38 @@ class Integration: :param files: List of in memory files :return: HttpResponseRedirect to the recipe search showing all imported recipes """ - ignored_recipes = [] - try: - self.files = files - for f in files: - if '.zip' in f.name or '.paprikarecipes' in f.name: - import_zip = ZipFile(f.file) - for z in import_zip.filelist: - if self.import_file_name_filter(z): - recipe = self.get_recipe_from_file(BytesIO(import_zip.read(z.filename))) - recipe.keywords.add(self.keyword) - if duplicate := self.is_duplicate(recipe): - ignored_recipes.append(duplicate) - import_zip.close() - else: - recipe = self.get_recipe_from_file(f.file) - recipe.keywords.add(self.keyword) - if duplicate := self.is_duplicate(recipe): - ignored_recipes.append(duplicate) - except BadZipFile: - messages.add_message(self.request, messages.ERROR, _('Importer expected a .zip file. Did you choose the correct importer type for your data ?')) + with scope(space=self.request.space): + ignored_recipes = [] + try: + self.files = files + for f in files: + if '.zip' in f['name'] or '.paprikarecipes' in f['name']: + import_zip = ZipFile(f['file']) + for z in import_zip.filelist: + if self.import_file_name_filter(z): + recipe = self.get_recipe_from_file(BytesIO(import_zip.read(z.filename))) + recipe.keywords.add(self.keyword) + if duplicate := self.is_duplicate(recipe): + ignored_recipes.append(duplicate) + import_zip.close() + else: + recipe = self.get_recipe_from_file(f['file']) + recipe.keywords.add(self.keyword) + if duplicate := self.is_duplicate(recipe): + ignored_recipes.append(duplicate) + except BadZipFile: + messages.add_message(self.request, messages.ERROR, _('Importer expected a .zip file. Did you choose the correct importer type for your data ?')) - if len(ignored_recipes) > 0: - messages.add_message(self.request, messages.WARNING, _('The following recipes were ignored because they already existed:') + ' ' + ', '.join(ignored_recipes)) - return HttpResponseRedirect(reverse('view_search') + '?keywords=' + str(self.keyword.pk)) + if len(ignored_recipes) > 0: + messages.add_message(self.request, messages.WARNING, _('The following recipes were ignored because they already existed:') + ' ' + ', '.join(ignored_recipes)) + return HttpResponseRedirect(reverse('view_search') + '?keywords=' + str(self.keyword.pk)) def is_duplicate(self, recipe): """ Checks if a recipe is already present, if so deletes it :param recipe: Recipe object """ - if Recipe.objects.filter(space=self.request.space, name=recipe.name).exists(): + if Recipe.objects.filter(space=self.request.space, name=recipe.name).count() > 1: recipe.delete() return recipe.name else: diff --git a/cookbook/integration/mealie.py b/cookbook/integration/mealie.py index 2cce3163..207e130a 100644 --- a/cookbook/integration/mealie.py +++ b/cookbook/integration/mealie.py @@ -40,8 +40,8 @@ class Mealie(Integration): recipe.steps.add(step) for f in self.files: - if '.zip' in f.name: - import_zip = ZipFile(f.file) + if '.zip' in f['name']: + import_zip = ZipFile(f['file']) for z in import_zip.filelist: if re.match(f'^images/{recipe_json["slug"]}.jpg$', z.filename): self.import_recipe_image(recipe, BytesIO(import_zip.read(z.filename))) diff --git a/cookbook/integration/nextcloud_cookbook.py b/cookbook/integration/nextcloud_cookbook.py index 8d43dc9d..24d1d998 100644 --- a/cookbook/integration/nextcloud_cookbook.py +++ b/cookbook/integration/nextcloud_cookbook.py @@ -42,8 +42,8 @@ class NextcloudCookbook(Integration): recipe.steps.add(step) for f in self.files: - if '.zip' in f.name: - import_zip = ZipFile(f.file) + if '.zip' in f['name']: + import_zip = ZipFile(f['file']) for z in import_zip.filelist: if re.match(f'^Recipes/{recipe.name}/full.jpg$', z.filename): self.import_recipe_image(recipe, BytesIO(import_zip.read(z.filename))) diff --git a/cookbook/models.py b/cookbook/models.py index 20bd0f75..ba97c560 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -241,6 +241,20 @@ class SyncLog(models.Model, PermissionModelMixin): return f"{self.created_at}:{self.sync} - {self.status}" +class ImportLog(models.Model, PermissionModelMixin): + type = models.CharField(max_length=32) + running = models.BooleanField(default=True) + msg = models.TextField(default="") + created_at = models.DateTimeField(auto_now_add=True) + created_by = models.ForeignKey(User, on_delete=models.CASCADE) + + objects = ScopedManager(space='space') + space = models.ForeignKey(Space, on_delete=models.CASCADE) + + def __str__(self): + return f"{self.created_at}:{self.type} - {self.msg}" + + class Keyword(models.Model, PermissionModelMixin): name = models.CharField(max_length=64) icon = models.CharField(max_length=16, blank=True, null=True) diff --git a/cookbook/views/import_export.py b/cookbook/views/import_export.py index bf3f7c76..d70b2d07 100644 --- a/cookbook/views/import_export.py +++ b/cookbook/views/import_export.py @@ -1,4 +1,6 @@ import re +import threading +from io import BytesIO from django.contrib import messages from django.shortcuts import render @@ -37,7 +39,15 @@ def import_recipe(request): if form.is_valid(): try: integration = get_integration(request, form.cleaned_data['type']) - return integration.do_import(request.FILES.getlist('files')) + files = [] + for f in request.FILES.getlist('files'): + files.append({'file': BytesIO(f.read()), 'name': f.name}) + t = threading.Thread(target=integration.do_import, args=[files]) + t.setDaemon(True) + t.start() + + messages.add_message(request, messages.SUCCESS, 'Import started') + return render(request, 'import.html', {'form': form}) except NotImplementedError: messages.add_message(request, messages.ERROR, _('Importing is not implemented for this provider')) else: From 950315936e4b9c7475c9f9bdd185c6afee0e8291 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 18:30:12 +0100 Subject: [PATCH 92/96] import log working --- cookbook/admin.py | 9 +++++++- cookbook/integration/integration.py | 19 ++++++++++------ cookbook/migrations/0114_importlog.py | 31 +++++++++++++++++++++++++++ cookbook/models.py | 29 +++++++++++++------------ cookbook/views/import_export.py | 18 +++++++++------- 5 files changed, 77 insertions(+), 29 deletions(-) create mode 100644 cookbook/migrations/0114_importlog.py diff --git a/cookbook/admin.py b/cookbook/admin.py index b96fa2e4..85bfbe01 100644 --- a/cookbook/admin.py +++ b/cookbook/admin.py @@ -7,7 +7,7 @@ from .models import (Comment, CookLog, Food, Ingredient, InviteLink, Keyword, RecipeBook, RecipeBookEntry, RecipeImport, ShareLink, ShoppingList, ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage, Sync, SyncLog, Unit, UserPreference, - ViewLog, Supermarket, SupermarketCategory, SupermarketCategoryRelation) + ViewLog, Supermarket, SupermarketCategory, SupermarketCategoryRelation, ImportLog) class CustomUserAdmin(UserAdmin): @@ -213,3 +213,10 @@ class NutritionInformationAdmin(admin.ModelAdmin): admin.site.register(NutritionInformation, NutritionInformationAdmin) + + +class ImportLogAdmin(admin.ModelAdmin): + list_display = ('id', 'type', 'running', 'created_by', 'created_at',) + + +admin.site.register(ImportLog, ImportLogAdmin) diff --git a/cookbook/integration/integration.py b/cookbook/integration/integration.py index db543ac1..1745de44 100644 --- a/cookbook/integration/integration.py +++ b/cookbook/integration/integration.py @@ -20,14 +20,14 @@ class Integration: keyword = None files = None - def __init__(self, request): + def __init__(self, request, export_type): """ Integration for importing and exporting recipes :param request: request context of import session (used to link user to created objects) """ self.request = request self.keyword = Keyword.objects.create( - name=f'Import {date_format(datetime.datetime.now(), "DATETIME_FORMAT")}.{datetime.datetime.now().strftime("%S")}', + name=f'Import {export_type} {date_format(datetime.datetime.now(), "DATETIME_FORMAT")}.{datetime.datetime.now().strftime("%S")}', description=f'Imported by {request.user.get_user_name()} at {date_format(datetime.datetime.now(), "DATETIME_FORMAT")}', icon='📥', space=request.space @@ -77,10 +77,11 @@ class Integration: """ return True - def do_import(self, files): + def do_import(self, files, il): """ Imports given files :param files: List of in memory files + :param il: Import Log object to refresh while running :return: HttpResponseRedirect to the recipe search showing all imported recipes """ with scope(space=self.request.space): @@ -94,20 +95,26 @@ class Integration: if self.import_file_name_filter(z): recipe = self.get_recipe_from_file(BytesIO(import_zip.read(z.filename))) recipe.keywords.add(self.keyword) + il.msg += f'{recipe.pk} - {recipe.name} \n' if duplicate := self.is_duplicate(recipe): ignored_recipes.append(duplicate) import_zip.close() else: recipe = self.get_recipe_from_file(f['file']) recipe.keywords.add(self.keyword) + il.msg += f'{recipe.pk} - {recipe.name} \n' if duplicate := self.is_duplicate(recipe): ignored_recipes.append(duplicate) except BadZipFile: - messages.add_message(self.request, messages.ERROR, _('Importer expected a .zip file. Did you choose the correct importer type for your data ?')) + il.msg += 'ERROR ' + _('Importer expected a .zip file. Did you choose the correct importer type for your data ?') + '\n' if len(ignored_recipes) > 0: - messages.add_message(self.request, messages.WARNING, _('The following recipes were ignored because they already existed:') + ' ' + ', '.join(ignored_recipes)) - return HttpResponseRedirect(reverse('view_search') + '?keywords=' + str(self.keyword.pk)) + il.msg += _('The following recipes were ignored because they already existed:') + ' ' + ', '.join(ignored_recipes) + '\n' + + il.keyword = self.keyword + il.msg += (_('Imported %s recipes.') % Recipe.objects.filter(keywords=self.keyword).count()) + '\n' + il.running = False + il.save() def is_duplicate(self, recipe): """ diff --git a/cookbook/migrations/0114_importlog.py b/cookbook/migrations/0114_importlog.py new file mode 100644 index 00000000..df7f9c55 --- /dev/null +++ b/cookbook/migrations/0114_importlog.py @@ -0,0 +1,31 @@ +# Generated by Django 3.1.7 on 2021-03-18 17:23 + +import cookbook.models +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('cookbook', '0113_auto_20210317_2017'), + ] + + operations = [ + migrations.CreateModel( + name='ImportLog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('type', models.CharField(max_length=32)), + ('running', models.BooleanField(default=True)), + ('msg', models.TextField(default='')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('keyword', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.keyword')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index ba97c560..6295fb92 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -241,20 +241,6 @@ class SyncLog(models.Model, PermissionModelMixin): return f"{self.created_at}:{self.sync} - {self.status}" -class ImportLog(models.Model, PermissionModelMixin): - type = models.CharField(max_length=32) - running = models.BooleanField(default=True) - msg = models.TextField(default="") - created_at = models.DateTimeField(auto_now_add=True) - created_by = models.ForeignKey(User, on_delete=models.CASCADE) - - objects = ScopedManager(space='space') - space = models.ForeignKey(Space, on_delete=models.CASCADE) - - def __str__(self): - return f"{self.created_at}:{self.type} - {self.msg}" - - class Keyword(models.Model, PermissionModelMixin): name = models.CharField(max_length=64) icon = models.CharField(max_length=16, blank=True, null=True) @@ -655,3 +641,18 @@ class ViewLog(models.Model, PermissionModelMixin): def __str__(self): return self.recipe.name + + +class ImportLog(models.Model, PermissionModelMixin): + type = models.CharField(max_length=32) + running = models.BooleanField(default=True) + msg = models.TextField(default="") + keyword = models.ForeignKey(Keyword, null=True, blank=True, on_delete=models.SET_NULL) + created_at = models.DateTimeField(auto_now_add=True) + created_by = models.ForeignKey(User, on_delete=models.CASCADE) + + objects = ScopedManager(space='space') + space = models.ForeignKey(Space, on_delete=models.CASCADE) + + def __str__(self): + return f"{self.created_at}:{self.type}" diff --git a/cookbook/views/import_export.py b/cookbook/views/import_export.py index d70b2d07..b067afd5 100644 --- a/cookbook/views/import_export.py +++ b/cookbook/views/import_export.py @@ -14,22 +14,22 @@ from cookbook.integration.mealie import Mealie from cookbook.integration.nextcloud_cookbook import NextcloudCookbook from cookbook.integration.paprika import Paprika from cookbook.integration.safron import Safron -from cookbook.models import Recipe +from cookbook.models import Recipe, ImportLog def get_integration(request, export_type): if export_type == ImportExportBase.DEFAULT: - return Default(request) + return Default(request, export_type) if export_type == ImportExportBase.PAPRIKA: - return Paprika(request) + return Paprika(request, export_type) if export_type == ImportExportBase.NEXTCLOUD: - return NextcloudCookbook(request) + return NextcloudCookbook(request, export_type) if export_type == ImportExportBase.MEALIE: - return Mealie(request) + return Mealie(request, export_type) if export_type == ImportExportBase.CHOWDOWN: - return Chowdown(request) + return Chowdown(request, export_type) if export_type == ImportExportBase.SAFRON: - return Safron(request) + return Safron(request, export_type) @group_required('user') @@ -39,10 +39,12 @@ def import_recipe(request): if form.is_valid(): try: integration = get_integration(request, form.cleaned_data['type']) + + il = ImportLog.objects.create(type=form.cleaned_data['type'], created_by=request.user, space=request.space) files = [] for f in request.FILES.getlist('files'): files.append({'file': BytesIO(f.read()), 'name': f.name}) - t = threading.Thread(target=integration.do_import, args=[files]) + t = threading.Thread(target=integration.do_import, args=[files, il]) t.setDaemon(True) t.start() From de9456e3d7567fd882941a602559aec5748b96a2 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 18:48:29 +0100 Subject: [PATCH 93/96] import log api --- cookbook/serializer.py | 29 ++++++-- cookbook/tests/api/test_api_import_log.py | 86 +++++++++++++++++++++++ cookbook/urls.py | 1 + cookbook/views/api.py | 13 +++- 4 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 cookbook/tests/api/test_api_import_log.py diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 57ddb143..916460a0 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -13,7 +13,7 @@ from cookbook.models import (Comment, CookLog, Food, Ingredient, Keyword, RecipeBook, RecipeBookEntry, RecipeImport, ShareLink, ShoppingList, ShoppingListEntry, ShoppingListRecipe, Step, Storage, Sync, SyncLog, - Unit, UserPreference, ViewLog, SupermarketCategory, Supermarket, SupermarketCategoryRelation) + Unit, UserPreference, ViewLog, SupermarketCategory, Supermarket, SupermarketCategoryRelation, ImportLog) from cookbook.templatetags.custom_tags import markdown @@ -160,6 +160,7 @@ class KeywordSerializer(UniqueFieldsMixin, serializers.ModelSerializer): return obj class Meta: + list_serializer_class = SpaceFilterSerializer model = Keyword fields = ('id', 'name', 'icon', 'label', 'description', 'created_at', 'updated_at') @@ -424,7 +425,7 @@ class ShareLinkSerializer(SpacedModelSerializer): class CookLogSerializer(serializers.ModelSerializer): - def create(self, validated_data): # TODO make mixin + def create(self, validated_data): validated_data['created_by'] = self.context['request'].user validated_data['space'] = self.context['request'].space return super().create(validated_data) @@ -435,10 +436,30 @@ class CookLogSerializer(serializers.ModelSerializer): read_only_fields = ('id', 'created_by') -class ViewLogSerializer(SpacedModelSerializer): +class ViewLogSerializer(serializers.ModelSerializer): + def create(self, validated_data): + validated_data['created_by'] = self.context['request'].user + validated_data['space'] = self.context['request'].space + return super().create(validated_data) + class Meta: model = ViewLog - fields = '__all__' + fields = ('id', 'recipe', 'created_by', 'created_at') + read_only_fields = ('created_by',) + + +class ImportLogSerializer(serializers.ModelSerializer): + keyword = KeywordSerializer(read_only=True) + + def create(self, validated_data): + validated_data['created_by'] = self.context['request'].user + validated_data['space'] = self.context['request'].space + return super().create(validated_data) + + class Meta: + model = ImportLog + fields = ('id', 'type', 'msg', 'running', 'keyword', 'created_by', 'created_at') + read_only_fields = ('created_by',) # Export/Import Serializers diff --git a/cookbook/tests/api/test_api_import_log.py b/cookbook/tests/api/test_api_import_log.py new file mode 100644 index 00000000..427c9a08 --- /dev/null +++ b/cookbook/tests/api/test_api_import_log.py @@ -0,0 +1,86 @@ +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import Keyword, CookLog, ViewLog, ImportLog + +LIST_URL = 'api:importlog-list' +DETAIL_URL = 'api:importlog-detail' + + +@pytest.fixture() +def obj_1(space_1, u1_s1, recipe_1_s1): + return ImportLog.objects.create(type='test', created_by=auth.get_user(u1_s1), space=space_1) + + +@pytest.fixture +def obj_2(space_1, u1_s1, recipe_1_s1): + return ImportLog.objects.create(type='test', created_by=auth.get_user(u1_s1), space=space_1) + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], +]) +def test_list_permission(arg, request): + c = request.getfixturevalue(arg[0]) + assert c.get(reverse(LIST_URL)).status_code == arg[1] + + +def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 2 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0 + + obj_1.space = space_2 + obj_1.save() + + assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 1 + assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 1 + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 403], + ['u1_s1', 200], + ['a1_s1', 200], + ['g1_s2', 403], + ['u1_s2', 404], + ['a1_s2', 404], +]) +def test_update(arg, request, obj_1): + c = request.getfixturevalue(arg[0]) + r = c.patch( + reverse( + DETAIL_URL, + args={obj_1.id} + ), + {'msg': 'new'}, + content_type='application/json' + ) + assert r.status_code == arg[1] + + +def test_delete(u1_s1, u1_s2, obj_1): + r = u1_s2.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + assert r.status_code == 404 + + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={obj_1.id} + ) + ) + + assert r.status_code == 204 + with scopes_disabled(): + assert ImportLog.objects.count() == 0 diff --git a/cookbook/urls.py b/cookbook/urls.py index cc562653..47bf6b59 100644 --- a/cookbook/urls.py +++ b/cookbook/urls.py @@ -35,6 +35,7 @@ router.register(r'cook-log', api.CookLogViewSet) router.register(r'recipe-book', api.RecipeBookViewSet) router.register(r'recipe-book-entry', api.RecipeBookEntryViewSet) router.register(r'supermarket', api.SupermarketViewSet) +router.register(r'import-log', api.ImportLogViewSet) urlpatterns = [ path('', views.index, name='index'), diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 3db33066..784fb2b7 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -32,7 +32,7 @@ from cookbook.models import (CookLog, Food, Ingredient, Keyword, MealPlan, MealType, Recipe, RecipeBook, ShoppingList, ShoppingListEntry, ShoppingListRecipe, Step, Storage, Sync, SyncLog, Unit, UserPreference, - ViewLog, RecipeBookEntry, Supermarket) + ViewLog, RecipeBookEntry, Supermarket, ImportLog) from cookbook.provider.dropbox import Dropbox from cookbook.provider.local import Local from cookbook.provider.nextcloud import Nextcloud @@ -47,7 +47,7 @@ from cookbook.serializer import (FoodSerializer, IngredientSerializer, StorageSerializer, SyncLogSerializer, SyncSerializer, UnitSerializer, UserNameSerializer, UserPreferenceSerializer, - ViewLogSerializer, CookLogSerializer, RecipeBookEntrySerializer, RecipeOverviewSerializer, SupermarketSerializer) + ViewLogSerializer, CookLogSerializer, RecipeBookEntrySerializer, RecipeOverviewSerializer, SupermarketSerializer, ImportLogSerializer) from recipes.settings import DEMO @@ -393,6 +393,15 @@ class CookLogViewSet(viewsets.ModelViewSet): return self.queryset +class ImportLogViewSet(viewsets.ModelViewSet): + queryset = ImportLog.objects + serializer_class = ImportLogSerializer + permission_classes = [CustomIsUser] + + def get_queryset(self): + return self.queryset.filter(space=self.request.space).all() + + # -------------- non django rest api views -------------------- def get_recipe_provider(recipe): From 8a051b531d141849526b6c5572c857038f13997d Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 20:00:13 +0100 Subject: [PATCH 94/96] import response view --- cookbook/integration/integration.py | 2 +- cookbook/static/vue/import_response_view.html | 1 + .../static/vue/js/import_response_view.js | 1 + cookbook/static/vue/js/recipe_view.js | 2 +- cookbook/templates/import_response.html | 34 ++++++ cookbook/templates/sw.js | 2 +- cookbook/urls.py | 1 + cookbook/views/import_export.py | 10 +- .../ImportResponseView/ImportResponseView.vue | 110 ++++++++++++++++++ vue/src/apps/ImportResponseView/main.js | 8 ++ vue/src/utils/api.js | 10 ++ vue/vue.config.js | 4 + vue/webpack-stats.json | 2 +- 13 files changed, 181 insertions(+), 6 deletions(-) create mode 100644 cookbook/static/vue/import_response_view.html create mode 100644 cookbook/static/vue/js/import_response_view.js create mode 100644 cookbook/templates/import_response.html create mode 100644 vue/src/apps/ImportResponseView/ImportResponseView.vue create mode 100644 vue/src/apps/ImportResponseView/main.js diff --git a/cookbook/integration/integration.py b/cookbook/integration/integration.py index 1745de44..39d08c2b 100644 --- a/cookbook/integration/integration.py +++ b/cookbook/integration/integration.py @@ -109,7 +109,7 @@ class Integration: il.msg += 'ERROR ' + _('Importer expected a .zip file. Did you choose the correct importer type for your data ?') + '\n' if len(ignored_recipes) > 0: - il.msg += _('The following recipes were ignored because they already existed:') + ' ' + ', '.join(ignored_recipes) + '\n' + il.msg += '\n' + _('The following recipes were ignored because they already existed:') + ' ' + ', '.join(ignored_recipes) + '\n\n' il.keyword = self.keyword il.msg += (_('Imported %s recipes.') % Recipe.objects.filter(keywords=self.keyword).count()) + '\n' diff --git a/cookbook/static/vue/import_response_view.html b/cookbook/static/vue/import_response_view.html new file mode 100644 index 00000000..27032984 --- /dev/null +++ b/cookbook/static/vue/import_response_view.html @@ -0,0 +1 @@ +Vue App
\ No newline at end of file diff --git a/cookbook/static/vue/js/import_response_view.js b/cookbook/static/vue/js/import_response_view.js new file mode 100644 index 00000000..745ac32b --- /dev/null +++ b/cookbook/static/vue/js/import_response_view.js @@ -0,0 +1 @@ +(function(t){function n(n){for(var r,i,c=n[0],s=n[1],u=n[2],l=0,d=[];li?i=n+1:o=n+1;break}tn&&(o=i,r=a),!e)return[0,r,o];var s=Math.floor(r/o);return[s,r-s*o,o]}var a={methods:{makeToast:function(t,n){var e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return i(t,n,e)}}};function i(t,n){var e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,o=new r["a"];o.$bvToast.toast(n,{title:t,variant:e,toaster:"b-toaster-top-center",solid:!0})}var c={methods:{_:function(t){return s(t)}}};function s(t){return window.gettext(t)}var u={methods:{resolveDjangoUrl:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return f(t,n)}}};function f(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==n?window.Urls[t](n):window.Urls[t]()}function l(t){return window.USER_PREF[t]}function d(t,n){if(l("use_fractions")){var e="",r=o(t*n,9,!0);return r[0]>0&&(e+=r[0]),r[1]>0&&(e+=" ".concat(r[1],"").concat(r[2],"")),e}return p(t*n)}function p(t){var n=l("user_fractions")?l("user_fractions"):2;return+(Math.round(t+"e+".concat(n))+"e-".concat(n))}}}); \ No newline at end of file diff --git a/cookbook/static/vue/js/recipe_view.js b/cookbook/static/vue/js/recipe_view.js index 84307478..7aecdb4c 100644 --- a/cookbook/static/vue/js/recipe_view.js +++ b/cookbook/static/vue/js/recipe_view.js @@ -1 +1 @@ -(function(e){function t(t){for(var i,r,o=t[0],c=t[1],l=t[2],p=0,f=[];p0?s("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[s("div",{staticClass:"card border-primary"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),s("br"),s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-12"},[s("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),s("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[null!==e.recipe.image?s("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),s("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[s("div",{staticClass:"col-12"},[s("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?s("div",[s("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")||e.recipe.file_path.includes(".gif")?s("div",[s("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,i){return s("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[s("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:i,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),s("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[s("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=s("b85c"),o=s("5f5b"),c=(s("2dd8"),s("bc3a")),l=s.n(c),d=s("fa7d");function p(e){var t=Object(d["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),l.a.get(t).then((function(e){return e.data})).catch((function(e){_(e,"There was an error loading a resource!","danger")}))}function f(e){return l.a.post(Object(d["g"])("api:cooklog-list"),e).then((function(e){Object(d["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function u(e){return l.a.get(Object(d["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function m(e){return l.a.post(Object(d["g"])("api:recipebookentry-list"),e).then((function(e){Object(d["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){_(e,"There was an error creating a resource!","danger")}))}function _(e,t){if("response"in e){console.log(e.response);var s="statusText"in e.response?e.response.statusText:Object(d["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(d["f"])(s,t,"danger")}else Object(d["f"])("Error",t,"danger"),console.log(e)}l.a.defaults.xsrfCookieName="csrftoken",l.a.defaults.xsrfHeaderName="X-CSRFTOKEN";var v=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-8"},[s("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?s("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?s("small",{staticClass:"d-print-none"},[s("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),s("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[s("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?s("div",{staticClass:"col col-md-4"},[s("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[s("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(s){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),s("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[s("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?s("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[s("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?s("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),s("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[s("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[s("i",{staticClass:"far fa-check-circle"})])],1)]),s("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?s("div",{staticClass:"row"},[s("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[s("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?s("div",[s("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[s("div",[s("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[s("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),s("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[s("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[s("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),s("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},b=[],g=(s("a9e3"),function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[s("td",{attrs:{colspan:"5"}},[s("b",[e._v(e._s(e.ingredient.note))])])]:[s("td",[e.ingredient.checked?s("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():s("i",{staticClass:"far fa-check-circle text-primary"})]),s("td",[0!==e.ingredient.amount?s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),s("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():s("span",[e._v(e._s(e.ingredient.unit.name))])]),s("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?s("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?s("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),s("td",[e.ingredient.note?s("div",[s("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[s("i",{staticClass:"far fa-comment"})]),s("div",{staticClass:"d-none d-print-block"},[s("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)}),h=[],j={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[d["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},y=j,C=s("2877"),k=Object(C["a"])(y,g,h,!1,null,null,null),w=k.exports,x=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},O=[],S=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.number))}})},E=[],T={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.factor)}}},$=T,P=Object(C["a"])($,S,E,!1,null,null,null),M=P.exports,z={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=i["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:M},template:"
".concat(this.code,"
")})}},N=z,D=Object(C["a"])(N,x,O,!1,null,null,null),R=D.exports,U=s("c1df"),H=s.n(U);i["default"].prototype.moment=H.a;var I={name:"Step",mixins:[d["a"]],components:{Ingredient:w,CompileComponent:R},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=H()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)},updateTime:function(){var e=H()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},A=I,L=Object(C["a"])(A,v,b,!1,null,null,null),B=L.exports,V=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("div",{staticClass:"dropdown"},[e._m(0),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[s("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[s("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?recipe="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),s("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[s("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),s("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[s("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?s("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[s("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),s("cook-log",{attrs:{recipe:e.recipe}})],1)},F=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[s("i",{staticClass:"fas fa-ellipsis-v"})])}],q=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[s("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),s("form",[s("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),s("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),s("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),s("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),s("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),s("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},J=[];i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var K={name:"CookLog",mixins:[d["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:H()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){f(this.logObject)}}},G=K,X=Object(C["a"])(G,q,J,!1,null,null,null),W=X.exports,Q={name:"RecipeContextMenu",mixins:[d["b"],d["a"]],components:{CookLog:W},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},Y=Q,Z=Object(C["a"])(Y,V,F,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},se=[],ie={name:"PdfViewer",mixins:[d["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},ae=ie,ne=Object(C["a"])(ae,te,se,!1,null,null,null),re=ne.exports,oe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticStyle:{"text-align":"center"}},[s("b-img",{attrs:{src:e.pdfUrl,alt:e._("External Recipe Image")}})],1)},ce=[],le={name:"ImageViewer",mixins:[d["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(d["g"])("api_get_recipe_file",this.recipe.id)}}},de=le,pe=Object(C["a"])(de,oe,ce,!1,null,null,null),fe=pe.exports,ue=function(){var e=this,t=e.$createElement,s=e._self._c||t;return null!==e.recipe.nutrition?s("div",[s("div",{staticClass:"card border-success"},[s("div",{staticClass:"card-body"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12"},[s("h4",{staticClass:"card-title"},[s("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.calories))}}),e._v(" kcal ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.fats))}}),e._v(" g ")])]),s("div",{staticClass:"row"},[s("div",{staticClass:"col-6"},[s("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),s("div",{staticClass:"col-6"},[s("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.proteins))}}),e._v(" g ")])])])])]):e._e()},me=[],_e={name:"Nutrition",mixins:[d["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(d["d"])(e,this.ingredient_factor)}}},ve=_e,be=Object(C["a"])(ve,ue,me,!1,null,null,null),ge=be.exports,he=function(){var e=this,t=e.$createElement,s=e._self._c||t;return e.recipe.keywords.length>0?s("div",e._l(e.recipe.keywords,(function(t){return s("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},je=[],ye={name:"Keywords",props:{recipe:Object}},Ce=ye,ke=Object(C["a"])(Ce,he,je,!1,null,null,null),we=ke.exports,xe=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},Oe=[function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",{staticClass:"row"},[s("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[s("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],Se={name:"LoadingSpinner",props:{recipe:Object}},Ee=Se,Te=Object(C["a"])(Ee,xe,Oe,!1,null,null,null),$e=Te.exports,Pe=function(){var e=this,t=e.$createElement,s=e._self._c||t;return s("div",[s("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[s("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},Me=[],ze=s("8e5f"),Ne=s.n(ze);i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var De={name:"AddRecipeToBook",mixins:[d["a"]],components:{Multiselect:Ne.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;u(e).then((function(e){t.books=e}))},addToBook:function(){m({recipe:this.recipe.id,book:this.selected_book.id})}}},Re=De,Ue=(s("60bc"),Object(C["a"])(Re,Pe,Me,!1,null,null,null)),He=Ue.exports;i["default"].prototype.moment=H.a,i["default"].use(o["a"]);var Ie={name:"RecipeView",mixins:[d["a"],d["b"],d["c"]],components:{PdfViewer:re,ImageViewer:fe,Ingredient:w,Step:B,RecipeContextMenu:ee,Nutrition:ge,Keywords:we,LoadingSpinner:$e,AddRecipeToBook:He},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;p(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var s,i=0,a=Object(r["a"])(e.steps);try{for(a.s();!(s=a.n()).done;){var n=s.value;t.ingredient_count+=n.ingredients.length;var o,c=Object(r["a"])(n.ingredients);try{for(c.s();!(o=c.n()).done;){var l=o.value;t.$set(l,"checked",!1)}}catch(d){c.e(d)}finally{c.f()}n.time_offset=i,i+=n.time}}catch(d){a.e(d)}finally{a.f()}i>0&&(t.start_time=H()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,s=Object(r["a"])(this.recipe.steps);try{for(s.s();!(t=s.n()).done;){var i,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(i=n.n()).done;){var o=i.value;o.id===e.id&&this.$set(o,"checked",!o.checked)}}catch(c){n.e(c)}finally{n.f()}}}catch(c){s.e(c)}finally{s.f()}}}},Ae=Ie,Le=Object(C["a"])(Ae,a,n,!1,null,null,null),Be=Le.exports;i["default"].config.productionTip=!1,new i["default"]({render:function(e){return e(Be)}}).$mount("#app")},4678:function(e,t,s){var i={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return s(t)}function n(e){if(!s.o(i,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=n,e.exports=a,a.id="4678"},fa7d:function(e,t,s){"use strict";s.d(t,"c",(function(){return n})),s.d(t,"f",(function(){return r})),s.d(t,"a",(function(){return o})),s.d(t,"e",(function(){return c})),s.d(t,"b",(function(){return l})),s.d(t,"g",(function(){return d})),s.d(t,"d",(function(){return f}));s("99af");var i=s("59e4");function a(e,t,s){var i=Math.floor(e),a=1,n=i+1,r=1;if(e!==i)while(a<=t&&r<=t){var o=(i+n)/(a+r);if(e===o){a+r<=t?(a+=r,i+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,i=n),!s)return[0,i,a];var c=Math.floor(i/a);return[c,i-c*a,a]}var n={methods:{makeToast:function(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,s)}}};function r(e,t){var s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new i["a"];a.$bvToast.toast(t,{title:e,variant:s,toaster:"b-toaster-top-center",solid:!0})}var o={methods:{_:function(e){return c(e)}}};function c(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function p(e){return window.USER_PREF[e]}function f(e,t){if(p("use_fractions")){var s="",i=a(e*t,9,!0);return i[0]>0&&(s+=i[0]),i[1]>0&&(s+=" ".concat(i[1],"").concat(i[2],"")),s}return u(e*t)}function u(e){var t=p("user_fractions")?p("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file +(function(e){function t(t){for(var s,r,c=t[0],o=t[1],l=t[2],u=0,p=[];u0?i("div",{staticClass:"col-md-6 order-md-1 col-sm-12 order-sm-2 col-12 order-2"},[i("div",{staticClass:"card border-primary"},[i("div",{staticClass:"card-body"},[i("div",{staticClass:"row"},[i("div",{staticClass:"col col-md-8"},[i("h4",{staticClass:"card-title"},[i("i",{staticClass:"fas fa-pepper-hot"}),e._v(" "+e._s(e._("Ingredients")))])])]),i("br"),i("div",{staticClass:"row"},[i("div",{staticClass:"col-md-12"},[i("table",{staticClass:"table table-sm"},[e._l(e.recipe.steps,(function(t){return[e._l(t.ingredients,(function(t){return[i("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":e.updateIngredientCheckedState}})]}))]}))],2)])])])])]):e._e(),i("div",{staticClass:"col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2"},[i("div",{staticClass:"row"},[i("div",{staticClass:"col-12"},[null!==e.recipe.image?i("img",{staticClass:"img img-fluid rounded",staticStyle:{"max-height":"30vh"},attrs:{src:e.recipe.image,alt:e._("Recipe Image")}}):e._e()])]),i("div",{staticClass:"row",staticStyle:{"margin-top":"2vh","margin-bottom":"2vh"}},[i("div",{staticClass:"col-12"},[i("Nutrition",{attrs:{recipe:e.recipe,ingredient_factor:e.ingredient_factor}})],1)])])]),e.recipe.internal?e._e():[e.recipe.file_path.includes(".pdf")?i("div",[i("PdfViewer",{attrs:{recipe:e.recipe}})],1):e._e(),e.recipe.file_path.includes(".png")||e.recipe.file_path.includes(".jpg")||e.recipe.file_path.includes(".jpeg")||e.recipe.file_path.includes(".gif")?i("div",[i("ImageViewer",{attrs:{recipe:e.recipe}})],1):e._e()],e._l(e.recipe.steps,(function(t,s){return i("div",{key:t.id,staticStyle:{"margin-top":"1vh"}},[i("Step",{attrs:{recipe:e.recipe,step:t,ingredient_factor:e.ingredient_factor,index:s,start_time:e.start_time},on:{"update-start-time":e.updateStartTime,"checked-state-changed":e.updateIngredientCheckedState}})],1)}))],2),i("add-recipe-to-book",{attrs:{recipe:e.recipe}})],2)},n=[function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[i("i",{staticClass:"fas fa-user-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[i("i",{staticClass:"far fa-clock fa-2x text-primary"})])},function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"my-auto",staticStyle:{"padding-right":"4px"}},[i("i",{staticClass:"fas fa-pizza-slice fa-2x text-primary"})])}],r=i("b85c"),c=i("5f5b"),o=(i("2dd8"),i("7c15")),l=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",[i("hr"),"TEXT"===e.step.type?[e.recipe.steps.length>1?i("div",{staticClass:"row"},[i("div",{staticClass:"col col-md-8"},[i("h5",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))],0!==e.step.time?i("small",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[i("i",{staticClass:"fas fa-user-clock"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min"))+" ")]):e._e(),""!==e.start_time?i("small",{staticClass:"d-print-none"},[i("b-link",{attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")])],1):e._e()],2)]),i("div",{staticClass:"col col-md-4",staticStyle:{"text-align":"right"}},[i("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[i("i",{staticClass:"far fa-check-circle"})])],1)]):e._e(),i("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[i("div",{staticClass:"row"},[e.step.ingredients.length>0&&e.recipe.steps.length>1?i("div",{staticClass:"col col-md-4"},[i("table",{staticClass:"table table-sm"},[e._l(e.step.ingredients,(function(t){return[i("Ingredient",{key:t.id,attrs:{ingredient:t,ingredient_factor:e.ingredient_factor},on:{"checked-state-changed":function(i){return e.$emit("checked-state-changed",t)}}})]}))],2)]):e._e(),i("div",{staticClass:"col",class:{"col-md-8":e.recipe.steps.length>1,"col-md-12":e.recipe.steps.length<=1}},[i("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)])])]:e._e(),"TIME"===e.step.type?[i("div",{staticClass:"row"},[i("div",{staticClass:"col-md-8 offset-md-2",staticStyle:{"text-align":"center"}},[i("h4",{staticClass:"text-primary"},[e.step.name?[e._v(e._s(e.step.name))]:[e._v(e._s(e._("Step"))+" "+e._s(e.index+1))]],2),0!==e.step.time?i("span",{staticClass:"text-muted",staticStyle:{"margin-left":"4px"}},[i("i",{staticClass:"fa fa-stopwatch"}),e._v(" "+e._s(e.step.time)+" "+e._s(e._("min")))]):e._e(),""!==e.start_time?i("b-link",{staticClass:"d-print-none",attrs:{id:"id_reactive_popover_"+e.step.id,href:"#"},on:{click:e.openPopover}},[e._v(" "+e._s(e.moment(e.start_time).add(e.step.time_offset,"minutes").format("HH:mm"))+" ")]):e._e()],1),i("div",{staticClass:"col-md-2",staticStyle:{"text-align":"right"}},[i("b-button",{staticClass:"shadow-none",class:{"text-primary":e.details_visible,"text-success":!e.details_visible},staticStyle:{border:"none",background:"none"},on:{click:function(t){e.details_visible=!e.details_visible}}},[i("i",{staticClass:"far fa-check-circle"})])],1)]),i("b-collapse",{attrs:{id:"collapse-1"},model:{value:e.details_visible,callback:function(t){e.details_visible=t},expression:"details_visible"}},[""!==e.step.instruction?i("div",{staticClass:"row"},[i("div",{staticClass:"col col-md-12",staticStyle:{"text-align":"center"}},[i("compile-component",{attrs:{code:e.step.ingredients_markdown,ingredient_factor:e.ingredient_factor}})],1)]):e._e()])]:e._e(),""!==e.start_time?i("div",[i("b-popover",{ref:"id_reactive_popover_"+e.step.id,attrs:{target:"id_reactive_popover_"+e.step.id,triggers:"click",placement:"bottom",title:e._("Step start time")}},[i("div",[i("b-form-group",{staticClass:"mb-1",attrs:{label:"Time","label-for":"popover-input-1","label-cols":"3"}},[i("b-form-input",{attrs:{type:"datetime-local",id:"popover-input-1",size:"sm"},model:{value:e.set_time_input,callback:function(t){e.set_time_input=t},expression:"set_time_input"}})],1)],1),i("div",{staticClass:"row",staticStyle:{"margin-top":"1vh"}},[i("div",{staticClass:"col-12",staticStyle:{"text-align":"right"}},[i("b-button",{staticStyle:{"margin-right":"8px"},attrs:{size:"sm",variant:"secondary"},on:{click:e.closePopover}},[e._v("Cancel")]),i("b-button",{attrs:{size:"sm",variant:"primary"},on:{click:e.updateTime}},[e._v("Ok")])],1)])])],1):e._e()],2)},d=[],u=(i("a9e3"),i("fa7d")),p=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("tr",{on:{click:function(t){return e.$emit("checked-state-changed",e.ingredient)}}},[e.ingredient.is_header?[i("td",{attrs:{colspan:"5"}},[i("b",[e._v(e._s(e.ingredient.note))])])]:[i("td",[e.ingredient.checked?i("i",{staticClass:"far fa-check-circle text-success"}):e._e(),e.ingredient.checked?e._e():i("i",{staticClass:"far fa-check-circle text-primary"})]),i("td",[0!==e.ingredient.amount?i("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.ingredient.amount))}}):e._e()]),i("td",[null===e.ingredient.unit||e.ingredient.no_amount?e._e():i("span",[e._v(e._s(e.ingredient.unit.name))])]),i("td",[null!==e.ingredient.food?[null!==e.ingredient.food.recipe?i("a",{attrs:{href:e.resolveDjangoUrl("view_recipe",e.ingredient.food.recipe),target:"_blank",rel:"noopener noreferrer"}},[e._v(e._s(e.ingredient.food.name))]):e._e(),null===e.ingredient.food.recipe?i("span",[e._v(e._s(e.ingredient.food.name))]):e._e()]:e._e()],2),i("td",[e.ingredient.note?i("div",[i("span",{directives:[{name:"b-popover",rawName:"v-b-popover.hover",value:e.ingredient.note,expression:"ingredient.note",modifiers:{hover:!0}}],staticClass:"d-print-none"},[i("i",{staticClass:"far fa-comment"})]),i("div",{staticClass:"d-none d-print-block"},[i("i",{staticClass:"far fa-comment-alt"}),e._v(" "+e._s(e.ingredient.note)+" ")])]):e._e()])]],2)},f=[],m={name:"Ingredient",props:{ingredient:Object,ingredient_factor:{type:Number,default:1}},mixins:[u["b"]],data:function(){return{checked:!1}},methods:{calculateAmount:function(e){return Object(u["d"])(e,this.ingredient_factor)}}},_=m,v=i("2877"),b=Object(v["a"])(_,p,f,!1,null,null,null),g=b.exports,h=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",[i(e.compiled,{tag:"component",attrs:{ingredient_factor:e.ingredient_factor,code:e.code}})],1)},j=[],y=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.number))}})},C=[],k={name:"ScalableNumber",props:{number:Number,factor:{type:Number,default:4}},methods:{calculateAmount:function(e){return Object(u["d"])(e,this.factor)}}},w=k,x=Object(v["a"])(w,y,C,!1,null,null,null),O=x.exports,S={name:"CompileComponent",props:["code","ingredient_factor"],data:function(){return{compiled:null}},mounted:function(){this.compiled=s["default"].component("compiled-component",{props:["ingredient_factor","code"],components:{ScalableNumber:O},template:"
".concat(this.code,"
")})}},E=S,T=Object(v["a"])(E,h,j,!1,null,null,null),$=T.exports,P=i("c1df"),M=i.n(P);s["default"].prototype.moment=M.a;var z={name:"Step",mixins:[u["a"]],components:{Ingredient:g,CompileComponent:$},props:{step:Object,ingredient_factor:Number,index:Number,recipe:Object,start_time:String},data:function(){return{details_visible:!0,set_time_input:""}},mounted:function(){this.set_time_input=M()(this.start_time).add(this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm")},methods:{calculateAmount:function(e){return Object(u["d"])(e,this.ingredient_factor)},updateTime:function(){var e=M()(this.set_time_input).add(-1*this.step.time_offset,"minutes").format("yyyy-MM-DDTHH:mm");this.$emit("update-start-time",e),this.closePopover()},closePopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("close")},openPopover:function(){this.$refs["id_reactive_popover_".concat(this.step.id)].$emit("open")}}},N=z,D=Object(v["a"])(N,l,d,!1,null,null,null),R=D.exports,U=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",[i("div",{staticClass:"dropdown"},[e._m(0),i("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuLink"}},[i("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_recipe",e.recipe.id)}},[i("i",{staticClass:"fas fa-pencil-alt fa-fw"}),e._v(" "+e._s(e._("Edit")))]),e.recipe.internal?e._e():i("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("edit_convert_recipe",e.recipe.id)}},[i("i",{staticClass:"fas fa-exchange-alt fa-fw"}),e._v(" "+e._s(e._("Convert to internal recipe")))]),i("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_add_book")}}},[i("i",{staticClass:"fas fa-bookmark fa-fw"}),e._v(" "+e._s(e._("Add to Book"))+" ")]),e.recipe.internal?i("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_shopping")+"?r=["+e.recipe.id+","+e.servings_value+"]",target:"_blank",rel:"noopener noreferrer"}},[i("i",{staticClass:"fas fa-shopping-cart fa-fw"}),e._v(" "+e._s(e._("Add to Shopping"))+" ")]):e._e(),i("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_meal_plan")+"?recipe="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[i("i",{staticClass:"fas fa-calendar fa-fw"}),e._v(" "+e._s(e._("Add to Plan"))+" ")]),i("button",{staticClass:"dropdown-item",on:{click:function(t){return e.$bvModal.show("id_modal_cook_log")}}},[i("i",{staticClass:"fas fa-clipboard-list fa-fw"}),e._v(" "+e._s(e._("Log Cooking"))+" ")]),i("button",{staticClass:"dropdown-item",attrs:{onclick:"window.print()"}},[i("i",{staticClass:"fas fa-print fa-fw"}),e._v(" "+e._s(e._("Print"))+" ")]),i("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("view_export")+"?r="+e.recipe.id,target:"_blank",rel:"noopener noreferrer"}},[i("i",{staticClass:"fas fa-file-export fa-fw"}),e._v(" "+e._s(e._("Export")))]),e.recipe.internal?i("a",{staticClass:"dropdown-item",attrs:{href:e.resolveDjangoUrl("new_share_link",e.recipe.id),target:"_blank",rel:"noopener noreferrer"}},[i("i",{staticClass:"fas fa-share-alt fa-fw"}),e._v(" "+e._s(e._("Share")))]):e._e()])]),i("cook-log",{attrs:{recipe:e.recipe}})],1)},H=[function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("a",{staticClass:"btn shadow-none",attrs:{href:"#",role:"button",id:"dropdownMenuLink","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false"}},[i("i",{staticClass:"fas fa-ellipsis-v"})])}],I=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",[i("b-modal",{staticClass:"modal",attrs:{id:"id_modal_cook_log",title:e._("Log Recipe Cooking"),"ok-title":e._("Save"),"cancel-title":e._("Close")},on:{ok:function(t){return e.logCook()}}},[i("p",[e._v(e._s(e._("All fields are optional and can be left empty.")))]),i("form",[i("label",{attrs:{for:"id_log_servings"}},[e._v(e._s(e._("Servings")))]),i("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.servings,expression:"logObject.servings"}],staticClass:"form-control",attrs:{type:"number",id:"id_log_servings"},domProps:{value:e.logObject.servings},on:{input:function(t){t.target.composing||e.$set(e.logObject,"servings",t.target.value)}}}),i("label",{staticStyle:{"margin-top":"2vh"}},[e._v(e._s(e._("Rating"))+" - "),i("span",{attrs:{id:"id_rating_show"}},[e._v(e._s(e.logObject.rating)+"/5")])]),i("b-form-rating",{model:{value:e.logObject.rating,callback:function(t){e.$set(e.logObject,"rating",t)},expression:"logObject.rating"}}),i("label",{staticStyle:{"margin-top":"2vh"},attrs:{for:"id_date"}},[e._v(e._s(e._("Date")))]),i("input",{directives:[{name:"model",rawName:"v-model",value:e.logObject.created_at,expression:"logObject.created_at"}],staticClass:"form-control",attrs:{type:"datetime-local",id:"id_date"},domProps:{value:e.logObject.created_at},on:{input:function(t){t.target.composing||e.$set(e.logObject,"created_at",t.target.value)}}})],1)])],1)},A=[];s["default"].prototype.moment=M.a,s["default"].use(c["a"]);var L={name:"CookLog",mixins:[u["a"]],props:{recipe:Object},data:function(){return{logObject:{recipe:this.recipe.id,servings:0,rating:0,created_at:M()().format("yyyy-MM-DDTHH:mm")}}},methods:{logCook:function(){Object(o["e"])(this.logObject)}}},B=L,V=Object(v["a"])(B,I,A,!1,null,null,null),F=V.exports,q={name:"RecipeContextMenu",mixins:[u["b"],u["a"]],components:{CookLog:F},data:function(){return{servings_value:0}},props:{recipe:Object,servings:{type:Number,default:-1}},mounted:function(){this.servings_value=-1===this.servings?this.recipe.servings:this.servings}},J=q,K=Object(v["a"])(J,U,H,!1,null,null,null),G=K.exports,X=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",[i("iframe",{staticStyle:{border:"none"},attrs:{src:e.pdfUrl,width:"100%",height:"700px"}})])},W=[],Q={name:"PdfViewer",mixins:[u["b"]],props:{recipe:Object},computed:{pdfUrl:function(){return"/static/pdfjs/viewer.html?file="+Object(u["g"])("api_get_recipe_file",this.recipe.id)}}},Y=Q,Z=Object(v["a"])(Y,X,W,!1,null,null,null),ee=Z.exports,te=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticStyle:{"text-align":"center"}},[i("b-img",{attrs:{src:e.pdfUrl,alt:e._("External Recipe Image")}})],1)},ie=[],se={name:"ImageViewer",mixins:[u["a"]],props:{recipe:Object},computed:{pdfUrl:function(){return Object(u["g"])("api_get_recipe_file",this.recipe.id)}}},ae=se,ne=Object(v["a"])(ae,te,ie,!1,null,null,null),re=ne.exports,ce=function(){var e=this,t=e.$createElement,i=e._self._c||t;return null!==e.recipe.nutrition?i("div",[i("div",{staticClass:"card border-success"},[i("div",{staticClass:"card-body"},[i("div",{staticClass:"row"},[i("div",{staticClass:"col-12"},[i("h4",{staticClass:"card-title"},[i("i",{staticClass:"fas fa-carrot"}),e._v(" "+e._s(e._("Nutrition")))])])]),i("div",{staticClass:"row"},[i("div",{staticClass:"col-6"},[i("i",{staticClass:"fas fa-fire fa-fw text-primary"}),e._v(" "+e._s(e._("Calories"))+" ")]),i("div",{staticClass:"col-6"},[i("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.calories))}}),e._v(" kcal ")])]),i("div",{staticClass:"row"},[i("div",{staticClass:"col-6"},[i("i",{staticClass:"fas fa-bread-slice fa-fw text-primary"}),e._v(" "+e._s(e._("Carbohydrates"))+" ")]),i("div",{staticClass:"col-6"},[i("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.carbohydrates))}}),e._v(" g ")])]),i("div",{staticClass:"row"},[i("div",{staticClass:"col-6"},[i("i",{staticClass:"fas fa-cheese fa-fw text-primary"}),e._v(" "+e._s(e._("Fats"))+" ")]),i("div",{staticClass:"col-6"},[i("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.fats))}}),e._v(" g ")])]),i("div",{staticClass:"row"},[i("div",{staticClass:"col-6"},[i("i",{staticClass:"fas fa-drumstick-bite fa-fw text-primary"}),e._v(" "+e._s(e._("Proteins"))+" ")]),i("div",{staticClass:"col-6"},[i("span",{domProps:{innerHTML:e._s(e.calculateAmount(e.recipe.nutrition.proteins))}}),e._v(" g ")])])])])]):e._e()},oe=[],le={name:"Nutrition",mixins:[u["a"]],props:{recipe:Object,ingredient_factor:Number},methods:{calculateAmount:function(e){return Object(u["d"])(e,this.ingredient_factor)}}},de=le,ue=Object(v["a"])(de,ce,oe,!1,null,null,null),pe=ue.exports,fe=function(){var e=this,t=e.$createElement,i=e._self._c||t;return e.recipe.keywords.length>0?i("div",e._l(e.recipe.keywords,(function(t){return i("small",{key:t.id,staticStyle:{padding:"2px"}},[e._v(" "+e._s(t.icon)+" "+e._s(t.name)+" ")])})),0):e._e()},me=[],_e={name:"Keywords",props:{recipe:Object}},ve=_e,be=Object(v["a"])(ve,fe,me,!1,null,null,null),ge=be.exports,he=i("d76c"),je=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",[i("b-modal",{staticClass:"modal",attrs:{id:"id_modal_add_book",title:e._("Add to Book"),"ok-title":e._("Add"),"cancel-title":e._("Close")},on:{ok:function(t){return e.addToBook()}}},[i("multiselect",{attrs:{options:e.books,"preserve-search":!0,placeholder:e._("Select Book"),label:"name","track-by":"id",id:"id_books",multiple:!1},on:{"search-change":e.loadBook},model:{value:e.selected_book,callback:function(t){e.selected_book=t},expression:"selected_book"}})],1)],1)},ye=[],Ce=i("8e5f"),ke=i.n(Ce);s["default"].prototype.moment=M.a,s["default"].use(c["a"]);var we={name:"AddRecipeToBook",mixins:[u["a"]],components:{Multiselect:ke.a},props:{recipe:Object},data:function(){return{books:[],selected_book:null}},mounted:function(){this.loadBook("")},methods:{loadBook:function(e){var t=this;Object(o["b"])(e).then((function(e){t.books=e}))},addToBook:function(){Object(o["a"])({recipe:this.recipe.id,book:this.selected_book.id})}}},xe=we,Oe=(i("60bc"),Object(v["a"])(xe,je,ye,!1,null,null,null)),Se=Oe.exports;s["default"].prototype.moment=M.a,s["default"].use(c["a"]);var Ee={name:"RecipeView",mixins:[u["a"],u["b"],u["c"]],components:{PdfViewer:ee,ImageViewer:re,Ingredient:g,Step:R,RecipeContextMenu:G,Nutrition:pe,Keywords:ge,LoadingSpinner:he["a"],AddRecipeToBook:Se},computed:{ingredient_factor:function(){return this.servings/this.recipe.servings}},data:function(){return{loading:!0,recipe:void 0,ingredient_count:0,servings:1,start_time:""}},mounted:function(){this.loadRecipe(window.RECIPE_ID)},methods:{loadRecipe:function(e){var t=this;Object(o["d"])(e).then((function(e){0!==window.USER_SERVINGS&&(e.servings=window.USER_SERVINGS),t.servings=e.servings;var i,s=0,a=Object(r["a"])(e.steps);try{for(a.s();!(i=a.n()).done;){var n=i.value;t.ingredient_count+=n.ingredients.length;var c,o=Object(r["a"])(n.ingredients);try{for(o.s();!(c=o.n()).done;){var l=c.value;t.$set(l,"checked",!1)}}catch(d){o.e(d)}finally{o.f()}n.time_offset=s,s+=n.time}}catch(d){a.e(d)}finally{a.f()}s>0&&(t.start_time=M()().format("yyyy-MM-DDTHH:mm")),t.recipe=e,t.loading=!1}))},updateStartTime:function(e){this.start_time=e},updateIngredientCheckedState:function(e){var t,i=Object(r["a"])(this.recipe.steps);try{for(i.s();!(t=i.n()).done;){var s,a=t.value,n=Object(r["a"])(a.ingredients);try{for(n.s();!(s=n.n()).done;){var c=s.value;c.id===e.id&&this.$set(c,"checked",!c.checked)}}catch(o){n.e(o)}finally{n.f()}}}catch(o){i.e(o)}finally{i.f()}}}},Te=Ee,$e=Object(v["a"])(Te,a,n,!1,null,null,null),Pe=$e.exports;s["default"].config.productionTip=!1,new s["default"]({render:function(e){return e(Pe)}}).$mount("#app")},4678:function(e,t,i){var s={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn-bd":"9686","./bn-bd.js":"9686","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-mx":"b5b7","./es-mx.js":"b5b7","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf755","./tlh.js":"cf755","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function a(e){var t=n(e);return i(t)}function n(e){if(!i.o(s,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return s[e]}a.keys=function(){return Object.keys(s)},a.resolve=n,e.exports=a,a.id="4678"},"7c15":function(e,t,i){"use strict";i.d(t,"d",(function(){return r})),i.d(t,"c",(function(){return c})),i.d(t,"e",(function(){return o})),i.d(t,"b",(function(){return l})),i.d(t,"a",(function(){return d}));var s=i("bc3a"),a=i.n(s),n=i("fa7d");function r(e){var t=Object(n["g"])("api:recipe-detail",e);return void 0!==window.SHARE_UID&&(t+="?share="+window.SHARE_UID),a.a.get(t).then((function(e){return e.data})).catch((function(e){u(e,"There was an error loading a resource!","danger")}))}function c(e){var t=Object(n["g"])("api:importlog-detail",e);return a.a.get(t).then((function(e){return e.data})).catch((function(e){u(e,"There was an error loading a resource!","danger")}))}function o(e){return a.a.post(Object(n["g"])("api:cooklog-list"),e).then((function(e){Object(n["f"])("Saved","Cook Log entry saved!","success")})).catch((function(e){u(e,"There was an error creating a resource!","danger")}))}function l(e){return a.a.get(Object(n["g"])("api:recipebook-list")+"?query="+e).then((function(e){return e.data})).catch((function(e){u(e,"There was an error creating a resource!","danger")}))}function d(e){return a.a.post(Object(n["g"])("api:recipebookentry-list"),e).then((function(e){Object(n["f"])("Saved","Recipe Book entry saved!","success")})).catch((function(e){u(e,"There was an error creating a resource!","danger")}))}function u(e,t){if("response"in e){console.log(e.response);var i="statusText"in e.response?e.response.statusText:Object(n["e"])("Error");t+="\n\n"+JSON.stringify(e.response.data),Object(n["f"])(i,t,"danger")}else Object(n["f"])("Error",t,"danger"),console.log(e)}a.a.defaults.xsrfCookieName="csrftoken",a.a.defaults.xsrfHeaderName="X-CSRFTOKEN"},d76c:function(e,t,i){"use strict";var s=function(){var e=this,t=e.$createElement;e._self._c;return e._m(0)},a=[function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"row"},[i("div",{staticClass:"col",staticStyle:{"text-align":"center"}},[i("i",{staticClass:"fas fa-spinner fa-spin fa-10x"})])])}],n={name:"LoadingSpinner",props:{recipe:Object}},r=n,c=i("2877"),o=Object(c["a"])(r,s,a,!1,null,null,null);t["a"]=o.exports},fa7d:function(e,t,i){"use strict";i.d(t,"c",(function(){return n})),i.d(t,"f",(function(){return r})),i.d(t,"a",(function(){return c})),i.d(t,"e",(function(){return o})),i.d(t,"b",(function(){return l})),i.d(t,"g",(function(){return d})),i.d(t,"d",(function(){return p}));i("99af");var s=i("59e4");function a(e,t,i){var s=Math.floor(e),a=1,n=s+1,r=1;if(e!==s)while(a<=t&&r<=t){var c=(s+n)/(a+r);if(e===c){a+r<=t?(a+=r,s+=n,r=t+1):a>r?r=t+1:a=t+1;break}et&&(a=r,s=n),!i)return[0,s,a];var o=Math.floor(s/a);return[o,s-o*a,a]}var n={methods:{makeToast:function(e,t){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return r(e,t,i)}}};function r(e,t){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=new s["a"];a.$bvToast.toast(t,{title:e,variant:i,toaster:"b-toaster-top-center",solid:!0})}var c={methods:{_:function(e){return o(e)}}};function o(e){return window.gettext(e)}var l={methods:{resolveDjangoUrl:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return d(e,t)}}};function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return null!==t?window.Urls[e](t):window.Urls[e]()}function u(e){return window.USER_PREF[e]}function p(e,t){if(u("use_fractions")){var i="",s=a(e*t,9,!0);return s[0]>0&&(i+=s[0]),s[1]>0&&(i+=" ".concat(s[1],"").concat(s[2],"")),i}return f(e*t)}function f(e){var t=u("user_fractions")?u("user_fractions"):2;return+(Math.round(e+"e+".concat(t))+"e-".concat(t))}}}); \ No newline at end of file diff --git a/cookbook/templates/import_response.html b/cookbook/templates/import_response.html new file mode 100644 index 00000000..e47ef734 --- /dev/null +++ b/cookbook/templates/import_response.html @@ -0,0 +1,34 @@ +{% extends "base.html" %} +{% load render_bundle from webpack_loader %} +{% load static %} +{% load i18n %} +{% load l10n %} + +{% block title %}{% trans 'Import' %}{% endblock %} + +{% block content %} + +
+ +
+ + +{% endblock %} + + +{% block script %} + + + {% if debug %} + + {% else %} + + {% endif %} + + + + {% render_bundle 'chunk-vendors' %} + {% render_bundle 'import_response_view' %} +{% endblock %} \ No newline at end of file diff --git a/cookbook/templates/sw.js b/cookbook/templates/sw.js index 5924313c..af71bd4b 100644 --- a/cookbook/templates/sw.js +++ b/cookbook/templates/sw.js @@ -1 +1 @@ -(function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"===typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(r,o,function(e){return t[e]}.bind(null,o));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t["default"]}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s="249e")})({"00ee":function(t,e,n){var r=n("b622"),o=r("toStringTag"),i={};i[o]="z",t.exports="[object z]"===String(i)},"06cf":function(t,e,n){var r=n("83ab"),o=n("d1e7"),i=n("5c6c"),a=n("fc6a"),c=n("c04e"),s=n("5135"),u=n("0cfb"),l=Object.getOwnPropertyDescriptor;e.f=r?l:function(t,e){if(t=a(t),e=c(e,!0),u)try{return l(t,e)}catch(n){}if(s(t,e))return i(!o.f.call(t,e),t[e])}},"0cfb":function(t,e,n){var r=n("83ab"),o=n("d039"),i=n("cc12");t.exports=!r&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},"14c3":function(t,e,n){var r=n("c6b6"),o=n("9263");t.exports=function(t,e){var n=t.exec;if("function"===typeof n){var i=n.call(t,e);if("object"!==typeof i)throw TypeError("RegExp exec method returned something other than an Object or null");return i}if("RegExp"!==r(t))throw TypeError("RegExp#exec called on incompatible receiver");return o.call(t,e)}},"1d80":function(t,e){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},"23cb":function(t,e,n){var r=n("a691"),o=Math.max,i=Math.min;t.exports=function(t,e){var n=r(t);return n<0?o(n+e,0):i(n,e)}},"23e7":function(t,e,n){var r=n("da84"),o=n("06cf").f,i=n("9112"),a=n("6eeb"),c=n("ce4e"),s=n("e893"),u=n("94ca");t.exports=function(t,e){var n,l,f,h,p,d,g=t.target,y=t.global,m=t.stat;if(l=y?r:m?r[g]||c(g,{}):(r[g]||{}).prototype,l)for(f in e){if(p=e[f],t.noTargetGet?(d=o(l,f),h=d&&d.value):h=l[f],n=u(y?f:g+(m?".":"#")+f,t.forced),!n&&void 0!==h){if(typeof p===typeof h)continue;s(p,h)}(t.sham||h&&h.sham)&&i(p,"sham",!0),a(l,f,p,t)}}},"241c":function(t,e,n){var r=n("ca84"),o=n("7839"),i=o.concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return r(t,i)}},"249e":function(t,e,n){"use strict";n.r(e);n("d3b7");function r(t,e,n,r,o,i,a){try{var c=t[i](a),s=c.value}catch(u){return void n(u)}c.done?e(s):Promise.resolve(s).then(r,o)}function o(t){return function(){var e=this,n=arguments;return new Promise((function(o,i){var a=t.apply(e,n);function c(t){r(a,o,i,c,s,"next",t)}function s(t){r(a,o,i,c,s,"throw",t)}c(void 0)}))}}n("466d"),n("ac1f"),n("4d63"),n("25f0"),n("96cf"),n("40b9");const i=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},a=i;class c extends Error{constructor(t,e){const n=a(t,e);super(n),this.name=t,this.details=e}}const s={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!==typeof registration?registration.scope:""},u=t=>[s.prefix,t,s.suffix].filter(t=>t&&t.length>0).join("-"),l=t=>{for(const e of Object.keys(s))t(e)},f={updateDetails:t=>{l(e=>{"string"===typeof t[e]&&(s[e]=t[e])})},getGoogleAnalyticsName:t=>t||u(s.googleAnalytics),getPrecacheName:t=>t||u(s.precache),getPrefix:()=>s.prefix,getRuntimeName:t=>t||u(s.runtime),getSuffix:()=>s.suffix};n("c700");let h;function p(){if(void 0===h){const e=new Response("");if("body"in e)try{new Response(e.body),h=!0}catch(t){h=!1}h=!1}return h}async function d(t,e){let n=null;if(t.url){const e=new URL(t.url);n=e.origin}if(n!==self.location.origin)throw new c("cross-origin-copy-response",{origin:n});const r=t.clone(),o={headers:new Headers(r.headers),status:r.status,statusText:r.statusText},i=e?e(o):o,a=p()?r.body:await r.blob();return new Response(a,i)}n("741b");const g={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!==typeof registration?registration.scope:""},y=t=>[g.prefix,t,g.suffix].filter(t=>t&&t.length>0).join("-"),m=t=>{for(const e of Object.keys(g))t(e)},v={updateDetails:t=>{m(e=>{"string"===typeof t[e]&&(g[e]=t[e])})},getGoogleAnalyticsName:t=>t||y(g.googleAnalytics),getPrecacheName:t=>t||y(g.precache),getPrefix:()=>g.prefix,getRuntimeName:t=>t||y(g.runtime),getSuffix:()=>g.suffix},w=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},x=w;class b extends Error{constructor(t,e){const n=x(t,e);super(n),this.name=t,this.details=e}}const _=t=>{const e=new URL(String(t),location.href);return e.href.replace(new RegExp("^"+location.origin),"")};function E(t,e){const n=new URL(t);for(const r of e)n.searchParams.delete(r);return n.href}async function R(t,e,n,r){const o=E(e.url,n);if(e.url===o)return t.match(e,r);const i={...r,ignoreSearch:!0},a=await t.keys(e,i);for(const c of a){const e=E(c.url,n);if(o===e)return t.match(c,r)}}class S{constructor(){this.promise=new Promise((t,e)=>{this.resolve=t,this.reject=e})}}const O=new Set;async function P(){for(const t of O)await t()}function N(t){return new Promise(e=>setTimeout(e,t))}n("6aa8");function k(t){return"string"===typeof t?new Request(t):t}class j{constructor(t,e){this._cacheKeys={},Object.assign(this,e),this.event=e.event,this._strategy=t,this._handlerDeferred=new S,this._extendLifetimePromises=[],this._plugins=[...t.plugins],this._pluginStateMap=new Map;for(const n of this._plugins)this._pluginStateMap.set(n,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(t){const{event:e}=this;let n=k(t);if("navigate"===n.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const r=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))n=await t({request:n.clone(),event:e})}catch(i){throw new b("plugin-error-request-will-fetch",{thrownError:i})}const o=n.clone();try{let t;t=await fetch(n,"navigate"===n.mode?void 0:this._strategy.fetchOptions);for(const n of this.iterateCallbacks("fetchDidSucceed"))t=await n({event:e,request:o,response:t});return t}catch(a){throw r&&await this.runCallbacks("fetchDidFail",{error:a,event:e,originalRequest:r.clone(),request:o.clone()}),a}}async fetchAndCachePut(t){const e=await this.fetch(t),n=e.clone();return this.waitUntil(this.cachePut(t,n)),e}async cacheMatch(t){const e=k(t);let n;const{cacheName:r,matchOptions:o}=this._strategy,i=await this.getCacheKey(e,"read"),a={...o,cacheName:r};n=await caches.match(i,a);for(const c of this.iterateCallbacks("cachedResponseWillBeUsed"))n=await c({cacheName:r,matchOptions:o,cachedResponse:n,request:i,event:this.event})||void 0;return n}async cachePut(t,e){const n=k(t);await N(0);const r=await this.getCacheKey(n,"write");if(!e)throw new b("cache-put-with-no-response",{url:_(r.url)});const o=await this._ensureResponseSafeToCache(e);if(!o)return!1;const{cacheName:i,matchOptions:a}=this._strategy,c=await self.caches.open(i),s=this.hasCallback("cacheDidUpdate"),u=s?await R(c,r.clone(),["__WB_REVISION__"],a):null;try{await c.put(r,s?o.clone():o)}catch(l){throw"QuotaExceededError"===l.name&&await P(),l}for(const f of this.iterateCallbacks("cacheDidUpdate"))await f({cacheName:i,oldResponse:u,newResponse:o.clone(),request:r,event:this.event});return!0}async getCacheKey(t,e){if(!this._cacheKeys[e]){let n=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))n=k(await t({mode:e,request:n,event:this.event,params:this.params}));this._cacheKeys[e]=n}return this._cacheKeys[e]}hasCallback(t){for(const e of this._strategy.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const n of this.iterateCallbacks(t))await n(e)}*iterateCallbacks(t){for(const e of this._strategy.plugins)if("function"===typeof e[t]){const n=this._pluginStateMap.get(e),r=r=>{const o={...r,state:n};return e[t](o)};yield r}}waitUntil(t){return this._extendLifetimePromises.push(t),t}async doneWaiting(){let t;while(t=this._extendLifetimePromises.shift())await t}destroy(){this._handlerDeferred.resolve()}async _ensureResponseSafeToCache(t){let e=t,n=!1;for(const r of this.iterateCallbacks("cacheWillUpdate"))if(e=await r({request:this.request,response:e,event:this.event})||void 0,n=!0,!e)break;return n||e&&200!==e.status&&(e=void 0),e}}class T{constructor(t={}){this.cacheName=v.getRuntimeName(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,n="string"===typeof t.request?new Request(t.request):t.request,r="params"in t?t.params:void 0,o=new j(this,{event:e,request:n,params:r}),i=this._getResponse(o,n,e),a=this._awaitComplete(i,o,n,e);return[i,a]}async _getResponse(t,e,n){await t.runCallbacks("handlerWillStart",{event:n,request:e});let r=void 0;try{if(r=await this._handle(e,t),!r||"error"===r.type)throw new b("no-response",{url:e.url})}catch(o){for(const i of t.iterateCallbacks("handlerDidError"))if(r=await i({error:o,event:n,request:e}),r)break;if(!r)throw o}for(const i of t.iterateCallbacks("handlerWillRespond"))r=await i({event:n,request:e,response:r});return r}async _awaitComplete(t,e,n,r){let o,i;try{o=await t}catch(i){}try{await e.runCallbacks("handlerDidRespond",{event:r,request:n,response:o}),await e.doneWaiting()}catch(a){i=a}if(await e.runCallbacks("handlerDidComplete",{event:r,request:n,response:o,error:i}),e.destroy(),i)throw i}}class C extends T{constructor(t={}){t.cacheName=f.getPrecacheName(t.cacheName),super(t),this._fallbackToNetwork=!1!==t.fallbackToNetwork,this.plugins.push(C.copyRedirectedCacheableResponsesPlugin)}async _handle(t,e){const n=await e.cacheMatch(t);return n||(e.event&&"install"===e.event.type?await this._handleInstall(t,e):await this._handleFetch(t,e))}async _handleFetch(t,e){let n;if(!this._fallbackToNetwork)throw new c("missing-precache-entry",{cacheName:this.cacheName,url:t.url});return n=await e.fetch(t),n}async _handleInstall(t,e){this._useDefaultCacheabilityPluginIfNeeded();const n=await e.fetch(t),r=await e.cachePut(t,n.clone());if(!r)throw new c("bad-precaching-response",{url:t.url,status:n.status});return n}_useDefaultCacheabilityPluginIfNeeded(){let t=null,e=0;for(const[n,r]of this.plugins.entries())r!==C.copyRedirectedCacheableResponsesPlugin&&(r===C.defaultPrecacheCacheabilityPlugin&&(t=n),r.cacheWillUpdate&&e++);0===e?this.plugins.push(C.defaultPrecacheCacheabilityPlugin):e>1&&null!==t&&this.plugins.splice(t,1)}}C.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:t}){return!t||t.status>=400?null:t}},C.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:t}){return t.redirected?await d(t):t}};n("95a8");const A=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},q=A;class L extends Error{constructor(t,e){const n=q(t,e);super(n),this.name=t,this.details=e}}n("e6d2");const M="GET",U=t=>t&&"object"===typeof t?t:{handle:t};class I{constructor(t,e,n=M){this.handler=U(e),this.match=t,this.method=n}setCatchHandler(t){this.catchHandler=U(t)}}class D extends I{constructor(t,e,n){const r=({url:e})=>{const n=t.exec(e.href);if(n&&(e.origin===location.origin||0===n.index))return n.slice(1)};super(r,e,n)}}class F{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener("fetch",t=>{const{request:e}=t,n=this.handleRequest({request:e,event:t});n&&t.respondWith(n)})}addCacheListener(){self.addEventListener("message",t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data;0;const n=Promise.all(e.urlsToCache.map(e=>{"string"===typeof e&&(e=[e]);const n=new Request(...e);return this.handleRequest({request:n,event:t})}));t.waitUntil(n),t.ports&&t.ports[0]&&n.then(()=>t.ports[0].postMessage(!0))}})}handleRequest({request:t,event:e}){const n=new URL(t.url,location.href);if(!n.protocol.startsWith("http"))return void 0;const r=n.origin===location.origin,{params:o,route:i}=this.findMatchingRoute({event:e,request:t,sameOrigin:r,url:n});let a=i&&i.handler;const c=t.method;if(!a&&this._defaultHandlerMap.has(c)&&(a=this._defaultHandlerMap.get(c)),!a)return void 0;let s;try{s=a.handle({url:n,request:t,event:e,params:o})}catch(l){s=Promise.reject(l)}const u=i&&i.catchHandler;return s instanceof Promise&&(this._catchHandler||u)&&(s=s.catch(async r=>{if(u){0;try{return await u.handle({url:n,request:t,event:e,params:o})}catch(i){r=i}}if(this._catchHandler)return this._catchHandler.handle({url:n,request:t,event:e});throw r})),s}findMatchingRoute({url:t,sameOrigin:e,request:n,event:r}){const o=this._routes.get(n.method)||[];for(const i of o){let o;const a=i.match({url:t,sameOrigin:e,request:n,event:r});if(a)return o=a,(Array.isArray(a)&&0===a.length||a.constructor===Object&&0===Object.keys(a).length||"boolean"===typeof a)&&(o=void 0),{route:i,params:o}}return{}}setDefaultHandler(t,e=M){this._defaultHandlerMap.set(e,U(t))}setCatchHandler(t){this._catchHandler=U(t)}registerRoute(t){this._routes.has(t.method)||this._routes.set(t.method,[]),this._routes.get(t.method).push(t)}unregisterRoute(t){if(!this._routes.has(t.method))throw new L("unregister-route-but-not-found-with-method",{method:t.method});const e=this._routes.get(t.method).indexOf(t);if(!(e>-1))throw new L("unregister-route-route-not-registered");this._routes.get(t.method).splice(e,1)}}let W;const H=()=>(W||(W=new F,W.addFetchListener(),W.addCacheListener()),W);function K(t,e,n){let r;if("string"===typeof t){const o=new URL(t,location.href);0;const i=({url:t})=>t.href===o.href;r=new I(i,e,n)}else if(t instanceof RegExp)r=new D(t,e,n);else if("function"===typeof t)r=new I(t,e,n);else{if(!(t instanceof I))throw new L("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});r=t}const o=H();return o.registerRoute(r),r}function G(t){const e=H();e.setCatchHandler(t)}class B extends T{async _handle(t,e){let n,r=await e.cacheMatch(t);if(r)0;else{0;try{r=await e.fetchAndCachePut(t)}catch(o){n=o}0}if(!r)throw new b("no-response",{url:t.url,error:n});return r}}const Y={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null};class $ extends T{constructor(t={}){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(Y),this._networkTimeoutSeconds=t.networkTimeoutSeconds||0}async _handle(t,e){const n=[];const r=[];let o;if(this._networkTimeoutSeconds){const{id:i,promise:a}=this._getTimeoutPromise({request:t,logs:n,handler:e});o=i,r.push(a)}const i=this._getNetworkPromise({timeoutId:o,request:t,logs:n,handler:e});r.push(i);const a=await e.waitUntil((async()=>await e.waitUntil(Promise.race(r))||await i)());if(!a)throw new b("no-response",{url:t.url});return a}_getTimeoutPromise({request:t,logs:e,handler:n}){let r;const o=new Promise(e=>{const o=async()=>{e(await n.cacheMatch(t))};r=setTimeout(o,1e3*this._networkTimeoutSeconds)});return{promise:o,id:r}}async _getNetworkPromise({timeoutId:t,request:e,logs:n,handler:r}){let o,i;try{i=await r.fetchAndCachePut(e)}catch(a){o=a}return t&&clearTimeout(t),!o&&i||(i=await r.cacheMatch(e)),i}}class z extends T{constructor(t){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(Y)}async _handle(t,e){const n=e.fetchAndCachePut(t).catch(()=>{});let r,o=await e.cacheMatch(t);if(o)0;else{0;try{o=await n}catch(i){r=i}}if(!o)throw new b("no-response",{url:t.url,error:r});return o}}n("d2e2");const J=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},Q=J;class V extends Error{constructor(t,e){const n=Q(t,e);super(n),this.name=t,this.details=e}}function X(t){t.then(()=>{})}class Z{constructor(t,e,{onupgradeneeded:n,onversionchange:r}={}){this._db=null,this._name=t,this._version=e,this._onupgradeneeded=n,this._onversionchange=r||(()=>this.close())}get db(){return this._db}async open(){if(!this._db)return this._db=await new Promise((t,e)=>{let n=!1;setTimeout(()=>{n=!0,e(new Error("The open request was blocked and timed out"))},this.OPEN_TIMEOUT);const r=indexedDB.open(this._name,this._version);r.onerror=()=>e(r.error),r.onupgradeneeded=t=>{n?(r.transaction.abort(),r.result.close()):"function"===typeof this._onupgradeneeded&&this._onupgradeneeded(t)},r.onsuccess=()=>{const e=r.result;n?e.close():(e.onversionchange=this._onversionchange.bind(this),t(e))}}),this}async getKey(t,e){return(await this.getAllKeys(t,e,1))[0]}async getAll(t,e,n){return await this.getAllMatching(t,{query:e,count:n})}async getAllKeys(t,e,n){const r=await this.getAllMatching(t,{query:e,count:n,includeKeys:!0});return r.map(t=>t.key)}async getAllMatching(t,{index:e,query:n=null,direction:r="next",count:o,includeKeys:i=!1}={}){return await this.transaction([t],"readonly",(a,c)=>{const s=a.objectStore(t),u=e?s.index(e):s,l=[],f=u.openCursor(n,r);f.onsuccess=()=>{const t=f.result;t?(l.push(i?t:t.value),o&&l.length>=o?c(l):t.continue()):c(l)}})}async transaction(t,e,n){return await this.open(),await new Promise((r,o)=>{const i=this._db.transaction(t,e);i.onabort=()=>o(i.error),i.oncomplete=()=>r(),n(i,t=>r(t))})}async _call(t,e,n,...r){const o=(n,o)=>{const i=n.objectStore(e),a=i[t].apply(i,r);a.onsuccess=()=>o(a.result)};return await this.transaction([e],n,o)}close(){this._db&&(this._db.close(),this._db=null)}}Z.prototype.OPEN_TIMEOUT=2e3;const tt={readonly:["get","count","getKey","getAll","getAllKeys"],readwrite:["add","put","clear","delete"]};for(const[yt,mt]of Object.entries(tt))for(const t of mt)t in IDBObjectStore.prototype&&(Z.prototype[t]=async function(e,...n){return await this._call(t,e,yt,...n)});const et=async t=>{await new Promise((e,n)=>{const r=indexedDB.deleteDatabase(t);r.onerror=()=>{n(r.error)},r.onblocked=()=>{n(new Error("Delete blocked"))},r.onsuccess=()=>{e()}})};n("d8a5");const nt="workbox-expiration",rt="cache-entries",ot=t=>{const e=new URL(t,location.href);return e.hash="",e.href};class it{constructor(t){this._cacheName=t,this._db=new Z(nt,1,{onupgradeneeded:t=>this._handleUpgrade(t)})}_handleUpgrade(t){const e=t.target.result,n=e.createObjectStore(rt,{keyPath:"id"});n.createIndex("cacheName","cacheName",{unique:!1}),n.createIndex("timestamp","timestamp",{unique:!1}),et(this._cacheName)}async setTimestamp(t,e){t=ot(t);const n={url:t,timestamp:e,cacheName:this._cacheName,id:this._getId(t)};await this._db.put(rt,n)}async getTimestamp(t){const e=await this._db.get(rt,this._getId(t));return e.timestamp}async expireEntries(t,e){const n=await this._db.transaction(rt,"readwrite",(n,r)=>{const o=n.objectStore(rt),i=o.index("timestamp").openCursor(null,"prev"),a=[];let c=0;i.onsuccess=()=>{const n=i.result;if(n){const r=n.value;r.cacheName===this._cacheName&&(t&&r.timestamp=e?a.push(n.value):c++),n.continue()}else r(a)}}),r=[];for(const o of n)await this._db.delete(rt,o.id),r.push(o.url);return r}_getId(t){return this._cacheName+"|"+ot(t)}}class at{constructor(t,e={}){this._isRunning=!1,this._rerunRequested=!1,this._maxEntries=e.maxEntries,this._maxAgeSeconds=e.maxAgeSeconds,this._matchOptions=e.matchOptions,this._cacheName=t,this._timestampModel=new it(t)}async expireEntries(){if(this._isRunning)return void(this._rerunRequested=!0);this._isRunning=!0;const t=this._maxAgeSeconds?Date.now()-1e3*this._maxAgeSeconds:0,e=await this._timestampModel.expireEntries(t,this._maxEntries),n=await self.caches.open(this._cacheName);for(const r of e)await n.delete(r,this._matchOptions);this._isRunning=!1,this._rerunRequested&&(this._rerunRequested=!1,X(this.expireEntries()))}async updateTimestamp(t){await this._timestampModel.setTimestamp(t,Date.now())}async isURLExpired(t){if(this._maxAgeSeconds){const e=await this._timestampModel.getTimestamp(t),n=Date.now()-1e3*this._maxAgeSeconds;return e[ct.prefix,t,ct.suffix].filter(t=>t&&t.length>0).join("-"),ut=t=>{for(const e of Object.keys(ct))t(e)},lt={updateDetails:t=>{ut(e=>{"string"===typeof t[e]&&(ct[e]=t[e])})},getGoogleAnalyticsName:t=>t||st(ct.googleAnalytics),getPrecacheName:t=>t||st(ct.precache),getPrefix:()=>ct.prefix,getRuntimeName:t=>t||st(ct.runtime),getSuffix:()=>ct.suffix},ft=new Set;function ht(t){ft.add(t)}class pt{constructor(t={}){this.cachedResponseWillBeUsed=async({event:t,request:e,cacheName:n,cachedResponse:r})=>{if(!r)return null;const o=this._isResponseDateFresh(r),i=this._getCacheExpiration(n);X(i.expireEntries());const a=i.updateTimestamp(e.url);if(t)try{t.waitUntil(a)}catch(c){0}return o?r:null},this.cacheDidUpdate=async({cacheName:t,request:e})=>{const n=this._getCacheExpiration(t);await n.updateTimestamp(e.url),await n.expireEntries()},this._config=t,this._maxAgeSeconds=t.maxAgeSeconds,this._cacheExpirations=new Map,t.purgeOnQuotaError&&ht(()=>this.deleteCacheAndMetadata())}_getCacheExpiration(t){if(t===lt.getRuntimeName())throw new V("expire-custom-caches-only");let e=this._cacheExpirations.get(t);return e||(e=new at(t,this._config),this._cacheExpirations.set(t,e)),e}_isResponseDateFresh(t){if(!this._maxAgeSeconds)return!0;const e=this._getDateHeaderTimestamp(t);if(null===e)return!0;const n=Date.now();return e>=n-1e3*this._maxAgeSeconds}_getDateHeaderTimestamp(t){if(!t.headers.has("date"))return null;const e=t.headers.get("date"),n=new Date(e),r=n.getTime();return isNaN(r)?null:r}async deleteCacheAndMetadata(){for(const[t,e]of this._cacheExpirations)await self.caches.delete(t),await e.delete();this._cacheExpirations=new Map}}var dt="offline-html",gt="/offline/";self.addEventListener("install",function(){var t=o(regeneratorRuntime.mark((function t(e){return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:e.waitUntil(caches.open(dt).then((function(t){return t.add(new Request(gt,{cache:"reload"}))})));case 1:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}()),[{'url':'static/vue/css/chunk-vendors.css'},{'url':'static/vue/js/chunk-vendors.js'},{'url':'static/vue/js/offline_view.js'},{'url':'static/vue/js/recipe_view.js'},{'url':'static/vue/manifest.json'},{'url':'static/vue/offline_view.html'},{'url':'static/vue/recipe_view.html'}],G((function(t){var e=t.event;switch(e.request.destination){case"document":return console.log("Triggered fallback HTML"),caches.open(dt).then((function(t){return t.match(gt)}));default:return console.log("Triggered response ERROR"),Response.error()}})),K((function(t){var e=t.request;return"image"===e.destination}),new B({cacheName:"images",plugins:[new pt({maxEntries:20})]})),K((function(t){var e=t.request;return"script"===e.destination||"style"===e.destination}),new z({cacheName:"assets"})),K(new RegExp("jsreverse"),new z({cacheName:"assets"})),K(new RegExp("jsi18n"),new z({cacheName:"assets"})),K(new RegExp("api/recipe/([0-9]+)"),new $({cacheName:"api-recipe",plugins:[new pt({maxEntries:50})]})),K(new RegExp("api/*"),new $({cacheName:"api",plugins:[new pt({maxEntries:50})]})),K((function(t){var e=t.request;return"document"===e.destination}),new $({cacheName:"html",plugins:[new pt({maxAgeSeconds:2592e3,maxEntries:50})]}))},"25f0":function(t,e,n){"use strict";var r=n("6eeb"),o=n("825a"),i=n("d039"),a=n("ad6d"),c="toString",s=RegExp.prototype,u=s[c],l=i((function(){return"/a/b"!=u.call({source:"a",flags:"b"})})),f=u.name!=c;(l||f)&&r(RegExp.prototype,c,(function(){var t=o(this),e=String(t.source),n=t.flags,r=String(void 0===n&&t instanceof RegExp&&!("flags"in s)?a.call(t):n);return"/"+e+"/"+r}),{unsafe:!0})},2626:function(t,e,n){"use strict";var r=n("d066"),o=n("9bf2"),i=n("b622"),a=n("83ab"),c=i("species");t.exports=function(t){var e=r(t),n=o.f;a&&e&&!e[c]&&n(e,c,{configurable:!0,get:function(){return this}})}},"2d00":function(t,e,n){var r,o,i=n("da84"),a=n("342f"),c=i.process,s=c&&c.versions,u=s&&s.v8;u?(r=u.split("."),o=r[0]+r[1]):a&&(r=a.match(/Edge\/(\d+)/),(!r||r[1]>=74)&&(r=a.match(/Chrome\/(\d+)/),r&&(o=r[1]))),t.exports=o&&+o},"342f":function(t,e,n){var r=n("d066");t.exports=r("navigator","userAgent")||""},"3bbe":function(t,e,n){var r=n("861d");t.exports=function(t){if(!r(t)&&null!==t)throw TypeError("Can't set "+String(t)+" as a prototype");return t}},"40b9":function(t,e,n){"use strict";try{self["workbox:core:6.1.2"]&&_()}catch(r){}},"428f":function(t,e,n){var r=n("da84");t.exports=r},"44ad":function(t,e,n){var r=n("d039"),o=n("c6b6"),i="".split;t.exports=r((function(){return!Object("z").propertyIsEnumerable(0)}))?function(t){return"String"==o(t)?i.call(t,""):Object(t)}:Object},"44e7":function(t,e,n){var r=n("861d"),o=n("c6b6"),i=n("b622"),a=i("match");t.exports=function(t){var e;return r(t)&&(void 0!==(e=t[a])?!!e:"RegExp"==o(t))}},"466d":function(t,e,n){"use strict";var r=n("d784"),o=n("825a"),i=n("50c4"),a=n("1d80"),c=n("8aa5"),s=n("14c3");r("match",1,(function(t,e,n){return[function(e){var n=a(this),r=void 0==e?void 0:e[t];return void 0!==r?r.call(e,n):new RegExp(e)[t](String(n))},function(t){var r=n(e,t,this);if(r.done)return r.value;var a=o(t),u=String(this);if(!a.global)return s(a,u);var l=a.unicode;a.lastIndex=0;var f,h=[],p=0;while(null!==(f=s(a,u))){var d=String(f[0]);h[p]=d,""===d&&(a.lastIndex=c(u,i(a.lastIndex),l)),p++}return 0===p?null:h}]}))},4930:function(t,e,n){var r=n("605d"),o=n("2d00"),i=n("d039");t.exports=!!Object.getOwnPropertySymbols&&!i((function(){return!Symbol.sham&&(r?38===o:o>37&&o<41)}))},"4d63":function(t,e,n){var r=n("83ab"),o=n("da84"),i=n("94ca"),a=n("7156"),c=n("9bf2").f,s=n("241c").f,u=n("44e7"),l=n("ad6d"),f=n("9f7f"),h=n("6eeb"),p=n("d039"),d=n("69f3").set,g=n("2626"),y=n("b622"),m=y("match"),v=o.RegExp,w=v.prototype,x=/a/g,b=/a/g,_=new v(x)!==x,E=f.UNSUPPORTED_Y,R=r&&i("RegExp",!_||E||p((function(){return b[m]=!1,v(x)!=x||v(b)==b||"/a/i"!=v(x,"i")})));if(R){var S=function(t,e){var n,r=this instanceof S,o=u(t),i=void 0===e;if(!r&&o&&t.constructor===S&&i)return t;_?o&&!i&&(t=t.source):t instanceof S&&(i&&(e=l.call(t)),t=t.source),E&&(n=!!e&&e.indexOf("y")>-1,n&&(e=e.replace(/y/g,"")));var c=a(_?new v(t,e):v(t,e),r?this:w,S);return E&&n&&d(c,{sticky:n}),c},O=function(t){t in S||c(S,t,{configurable:!0,get:function(){return v[t]},set:function(e){v[t]=e}})},P=s(v),N=0;while(P.length>N)O(P[N++]);w.constructor=S,S.prototype=w,h(o,"RegExp",S)}g("RegExp")},"4d64":function(t,e,n){var r=n("fc6a"),o=n("50c4"),i=n("23cb"),a=function(t){return function(e,n,a){var c,s=r(e),u=o(s.length),l=i(a,u);if(t&&n!=n){while(u>l)if(c=s[l++],c!=c)return!0}else for(;u>l;l++)if((t||l in s)&&s[l]===n)return t||l||0;return!t&&-1}};t.exports={includes:a(!0),indexOf:a(!1)}},"50c4":function(t,e,n){var r=n("a691"),o=Math.min;t.exports=function(t){return t>0?o(r(t),9007199254740991):0}},5135:function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},5692:function(t,e,n){var r=n("c430"),o=n("c6cd");(t.exports=function(t,e){return o[t]||(o[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.9.1",mode:r?"pure":"global",copyright:"© 2021 Denis Pushkarev (zloirock.ru)"})},"56ef":function(t,e,n){var r=n("d066"),o=n("241c"),i=n("7418"),a=n("825a");t.exports=r("Reflect","ownKeys")||function(t){var e=o.f(a(t)),n=i.f;return n?e.concat(n(t)):e}},"5c6c":function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},"605d":function(t,e,n){var r=n("c6b6"),o=n("da84");t.exports="process"==r(o.process)},6547:function(t,e,n){var r=n("a691"),o=n("1d80"),i=function(t){return function(e,n){var i,a,c=String(o(e)),s=r(n),u=c.length;return s<0||s>=u?t?"":void 0:(i=c.charCodeAt(s),i<55296||i>56319||s+1===u||(a=c.charCodeAt(s+1))<56320||a>57343?t?c.charAt(s):i:t?c.slice(s,s+2):a-56320+(i-55296<<10)+65536)}};t.exports={codeAt:i(!1),charAt:i(!0)}},"69f3":function(t,e,n){var r,o,i,a=n("7f9a"),c=n("da84"),s=n("861d"),u=n("9112"),l=n("5135"),f=n("c6cd"),h=n("f772"),p=n("d012"),d=c.WeakMap,g=function(t){return i(t)?o(t):r(t,{})},y=function(t){return function(e){var n;if(!s(e)||(n=o(e)).type!==t)throw TypeError("Incompatible receiver, "+t+" required");return n}};if(a){var m=f.state||(f.state=new d),v=m.get,w=m.has,x=m.set;r=function(t,e){return e.facade=t,x.call(m,t,e),e},o=function(t){return v.call(m,t)||{}},i=function(t){return w.call(m,t)}}else{var b=h("state");p[b]=!0,r=function(t,e){return e.facade=t,u(t,b,e),e},o=function(t){return l(t,b)?t[b]:{}},i=function(t){return l(t,b)}}t.exports={set:r,get:o,has:i,enforce:g,getterFor:y}},"6aa8":function(t,e,n){"use strict";try{self["workbox:strategies:6.1.2"]&&_()}catch(r){}},"6eeb":function(t,e,n){var r=n("da84"),o=n("9112"),i=n("5135"),a=n("ce4e"),c=n("8925"),s=n("69f3"),u=s.get,l=s.enforce,f=String(String).split("String");(t.exports=function(t,e,n,c){var s,u=!!c&&!!c.unsafe,h=!!c&&!!c.enumerable,p=!!c&&!!c.noTargetGet;"function"==typeof n&&("string"!=typeof e||i(n,"name")||o(n,"name",e),s=l(n),s.source||(s.source=f.join("string"==typeof e?e:""))),t!==r?(u?!p&&t[e]&&(h=!0):delete t[e],h?t[e]=n:o(t,e,n)):h?t[e]=n:a(e,n)})(Function.prototype,"toString",(function(){return"function"==typeof this&&u(this).source||c(this)}))},7156:function(t,e,n){var r=n("861d"),o=n("d2bb");t.exports=function(t,e,n){var i,a;return o&&"function"==typeof(i=e.constructor)&&i!==n&&r(a=i.prototype)&&a!==n.prototype&&o(t,a),t}},7418:function(t,e){e.f=Object.getOwnPropertySymbols},"741b":function(t,e,n){"use strict";try{self["workbox:core:6.1.2"]&&_()}catch(r){}},7839:function(t,e){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},"7f9a":function(t,e,n){var r=n("da84"),o=n("8925"),i=r.WeakMap;t.exports="function"===typeof i&&/native code/.test(o(i))},"825a":function(t,e,n){var r=n("861d");t.exports=function(t){if(!r(t))throw TypeError(String(t)+" is not an object");return t}},"83ab":function(t,e,n){var r=n("d039");t.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},"861d":function(t,e){t.exports=function(t){return"object"===typeof t?null!==t:"function"===typeof t}},8925:function(t,e,n){var r=n("c6cd"),o=Function.toString;"function"!=typeof r.inspectSource&&(r.inspectSource=function(t){return o.call(t)}),t.exports=r.inspectSource},"8aa5":function(t,e,n){"use strict";var r=n("6547").charAt;t.exports=function(t,e,n){return e+(n?r(t,e).length:1)}},"90e3":function(t,e){var n=0,r=Math.random();t.exports=function(t){return"Symbol("+String(void 0===t?"":t)+")_"+(++n+r).toString(36)}},9112:function(t,e,n){var r=n("83ab"),o=n("9bf2"),i=n("5c6c");t.exports=r?function(t,e,n){return o.f(t,e,i(1,n))}:function(t,e,n){return t[e]=n,t}},9263:function(t,e,n){"use strict";var r=n("ad6d"),o=n("9f7f"),i=RegExp.prototype.exec,a=String.prototype.replace,c=i,s=function(){var t=/a/,e=/b*/g;return i.call(t,"a"),i.call(e,"a"),0!==t.lastIndex||0!==e.lastIndex}(),u=o.UNSUPPORTED_Y||o.BROKEN_CARET,l=void 0!==/()??/.exec("")[1],f=s||l||u;f&&(c=function(t){var e,n,o,c,f=this,h=u&&f.sticky,p=r.call(f),d=f.source,g=0,y=t;return h&&(p=p.replace("y",""),-1===p.indexOf("g")&&(p+="g"),y=String(t).slice(f.lastIndex),f.lastIndex>0&&(!f.multiline||f.multiline&&"\n"!==t[f.lastIndex-1])&&(d="(?: "+d+")",y=" "+y,g++),n=new RegExp("^(?:"+d+")",p)),l&&(n=new RegExp("^"+d+"$(?!\\s)",p)),s&&(e=f.lastIndex),o=i.call(h?n:f,y),h?o?(o.input=o.input.slice(g),o[0]=o[0].slice(g),o.index=f.lastIndex,f.lastIndex+=o[0].length):f.lastIndex=0:s&&o&&(f.lastIndex=f.global?o.index+o[0].length:e),l&&o&&o.length>1&&a.call(o[0],n,(function(){for(c=1;c=0;--i){var a=this.tryEntries[i],c=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var s=r.call(a,"catchLoc"),u=r.call(a,"finallyLoc");if(s&&u){if(this.prev=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&r.call(o,"finallyLoc")&&this.prev=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),N(n),g}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var r=n.completion;if("throw"===r.type){var o=r.arg;N(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,n,r){return this.delegate={iterator:j(t),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=e),g}},t}(t.exports);try{regeneratorRuntime=r}catch(o){Function("r","regeneratorRuntime = r")(r)}},"9bf2":function(t,e,n){var r=n("83ab"),o=n("0cfb"),i=n("825a"),a=n("c04e"),c=Object.defineProperty;e.f=r?c:function(t,e,n){if(i(t),e=a(e,!0),i(n),o)try{return c(t,e,n)}catch(r){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(t[e]=n.value),t}},"9f7f":function(t,e,n){"use strict";var r=n("d039");function o(t,e){return RegExp(t,e)}e.UNSUPPORTED_Y=r((function(){var t=o("a","y");return t.lastIndex=2,null!=t.exec("abcd")})),e.BROKEN_CARET=r((function(){var t=o("^r","gy");return t.lastIndex=2,null!=t.exec("str")}))},a691:function(t,e){var n=Math.ceil,r=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?r:n)(t)}},ac1f:function(t,e,n){"use strict";var r=n("23e7"),o=n("9263");r({target:"RegExp",proto:!0,forced:/./.exec!==o},{exec:o})},ad6d:function(t,e,n){"use strict";var r=n("825a");t.exports=function(){var t=r(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.dotAll&&(e+="s"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},b041:function(t,e,n){"use strict";var r=n("00ee"),o=n("f5df");t.exports=r?{}.toString:function(){return"[object "+o(this)+"]"}},b622:function(t,e,n){var r=n("da84"),o=n("5692"),i=n("5135"),a=n("90e3"),c=n("4930"),s=n("fdbf"),u=o("wks"),l=r.Symbol,f=s?l:l&&l.withoutSetter||a;t.exports=function(t){return i(u,t)&&(c||"string"==typeof u[t])||(c&&i(l,t)?u[t]=l[t]:u[t]=f("Symbol."+t)),u[t]}},c04e:function(t,e,n){var r=n("861d");t.exports=function(t,e){if(!r(t))return t;var n,o;if(e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;if("function"==typeof(n=t.valueOf)&&!r(o=n.call(t)))return o;if(!e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;throw TypeError("Can't convert object to primitive value")}},c430:function(t,e){t.exports=!1},c6b6:function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},c6cd:function(t,e,n){var r=n("da84"),o=n("ce4e"),i="__core-js_shared__",a=r[i]||o(i,{});t.exports=a},c700:function(t,e,n){"use strict";try{self["workbox:precaching:6.1.2"]&&_()}catch(r){}},c8ba:function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(r){"object"===typeof window&&(n=window)}t.exports=n},ca84:function(t,e,n){var r=n("5135"),o=n("fc6a"),i=n("4d64").indexOf,a=n("d012");t.exports=function(t,e){var n,c=o(t),s=0,u=[];for(n in c)!r(a,n)&&r(c,n)&&u.push(n);while(e.length>s)r(c,n=e[s++])&&(~i(u,n)||u.push(n));return u}},cc12:function(t,e,n){var r=n("da84"),o=n("861d"),i=r.document,a=o(i)&&o(i.createElement);t.exports=function(t){return a?i.createElement(t):{}}},ce4e:function(t,e,n){var r=n("da84"),o=n("9112");t.exports=function(t,e){try{o(r,t,e)}catch(n){r[t]=e}return e}},d012:function(t,e){t.exports={}},d039:function(t,e){t.exports=function(t){try{return!!t()}catch(e){return!0}}},d066:function(t,e,n){var r=n("428f"),o=n("da84"),i=function(t){return"function"==typeof t?t:void 0};t.exports=function(t,e){return arguments.length<2?i(r[t])||i(o[t]):r[t]&&r[t][e]||o[t]&&o[t][e]}},d1e7:function(t,e,n){"use strict";var r={}.propertyIsEnumerable,o=Object.getOwnPropertyDescriptor,i=o&&!r.call({1:2},1);e.f=i?function(t){var e=o(this,t);return!!e&&e.enumerable}:r},d2bb:function(t,e,n){var r=n("825a"),o=n("3bbe");t.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,n={};try{t=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set,t.call(n,[]),e=n instanceof Array}catch(i){}return function(n,i){return r(n),o(i),e?t.call(n,i):n.__proto__=i,n}}():void 0)},d2e2:function(t,e,n){"use strict";try{self["workbox:core:6.1.2"]&&_()}catch(r){}},d3b7:function(t,e,n){var r=n("00ee"),o=n("6eeb"),i=n("b041");r||o(Object.prototype,"toString",i,{unsafe:!0})},d784:function(t,e,n){"use strict";n("ac1f");var r=n("6eeb"),o=n("d039"),i=n("b622"),a=n("9263"),c=n("9112"),s=i("species"),u=!o((function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")})),l=function(){return"$0"==="a".replace(/./,"$0")}(),f=i("replace"),h=function(){return!!/./[f]&&""===/./[f]("a","$0")}(),p=!o((function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var n="ab".split(t);return 2!==n.length||"a"!==n[0]||"b"!==n[1]}));t.exports=function(t,e,n,f){var d=i(t),g=!o((function(){var e={};return e[d]=function(){return 7},7!=""[t](e)})),y=g&&!o((function(){var e=!1,n=/a/;return"split"===t&&(n={},n.constructor={},n.constructor[s]=function(){return n},n.flags="",n[d]=/./[d]),n.exec=function(){return e=!0,null},n[d](""),!e}));if(!g||!y||"replace"===t&&(!u||!l||h)||"split"===t&&!p){var m=/./[d],v=n(d,""[t],(function(t,e,n,r,o){return e.exec===a?g&&!o?{done:!0,value:m.call(e,n,r)}:{done:!0,value:t.call(n,e,r)}:{done:!1}}),{REPLACE_KEEPS_$0:l,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:h}),w=v[0],x=v[1];r(String.prototype,t,w),r(RegExp.prototype,d,2==e?function(t,e){return x.call(t,this,e)}:function(t){return x.call(t,this)})}f&&c(RegExp.prototype[d],"sham",!0)}},d8a5:function(t,e,n){"use strict";try{self["workbox:expiration:6.1.2"]&&_()}catch(r){}},da84:function(t,e,n){(function(e){var n=function(t){return t&&t.Math==Math&&t};t.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof e&&e)||function(){return this}()||Function("return this")()}).call(this,n("c8ba"))},e6d2:function(t,e,n){"use strict";try{self["workbox:routing:6.1.2"]&&_()}catch(r){}},e893:function(t,e,n){var r=n("5135"),o=n("56ef"),i=n("06cf"),a=n("9bf2");t.exports=function(t,e){for(var n=o(e),c=a.f,s=i.f,u=0;u{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},a=i;class c extends Error{constructor(t,e){const n=a(t,e);super(n),this.name=t,this.details=e}}const s={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!==typeof registration?registration.scope:""},u=t=>[s.prefix,t,s.suffix].filter(t=>t&&t.length>0).join("-"),l=t=>{for(const e of Object.keys(s))t(e)},f={updateDetails:t=>{l(e=>{"string"===typeof t[e]&&(s[e]=t[e])})},getGoogleAnalyticsName:t=>t||u(s.googleAnalytics),getPrecacheName:t=>t||u(s.precache),getPrefix:()=>s.prefix,getRuntimeName:t=>t||u(s.runtime),getSuffix:()=>s.suffix};n("c700");let h;function p(){if(void 0===h){const e=new Response("");if("body"in e)try{new Response(e.body),h=!0}catch(t){h=!1}h=!1}return h}async function d(t,e){let n=null;if(t.url){const e=new URL(t.url);n=e.origin}if(n!==self.location.origin)throw new c("cross-origin-copy-response",{origin:n});const r=t.clone(),o={headers:new Headers(r.headers),status:r.status,statusText:r.statusText},i=e?e(o):o,a=p()?r.body:await r.blob();return new Response(a,i)}n("741b");const g={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!==typeof registration?registration.scope:""},y=t=>[g.prefix,t,g.suffix].filter(t=>t&&t.length>0).join("-"),m=t=>{for(const e of Object.keys(g))t(e)},v={updateDetails:t=>{m(e=>{"string"===typeof t[e]&&(g[e]=t[e])})},getGoogleAnalyticsName:t=>t||y(g.googleAnalytics),getPrecacheName:t=>t||y(g.precache),getPrefix:()=>g.prefix,getRuntimeName:t=>t||y(g.runtime),getSuffix:()=>g.suffix},w=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},x=w;class b extends Error{constructor(t,e){const n=x(t,e);super(n),this.name=t,this.details=e}}const _=t=>{const e=new URL(String(t),location.href);return e.href.replace(new RegExp("^"+location.origin),"")};function E(t,e){const n=new URL(t);for(const r of e)n.searchParams.delete(r);return n.href}async function R(t,e,n,r){const o=E(e.url,n);if(e.url===o)return t.match(e,r);const i={...r,ignoreSearch:!0},a=await t.keys(e,i);for(const c of a){const e=E(c.url,n);if(o===e)return t.match(c,r)}}class S{constructor(){this.promise=new Promise((t,e)=>{this.resolve=t,this.reject=e})}}const O=new Set;async function P(){for(const t of O)await t()}function N(t){return new Promise(e=>setTimeout(e,t))}n("6aa8");function k(t){return"string"===typeof t?new Request(t):t}class j{constructor(t,e){this._cacheKeys={},Object.assign(this,e),this.event=e.event,this._strategy=t,this._handlerDeferred=new S,this._extendLifetimePromises=[],this._plugins=[...t.plugins],this._pluginStateMap=new Map;for(const n of this._plugins)this._pluginStateMap.set(n,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(t){const{event:e}=this;let n=k(t);if("navigate"===n.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const r=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))n=await t({request:n.clone(),event:e})}catch(i){throw new b("plugin-error-request-will-fetch",{thrownError:i})}const o=n.clone();try{let t;t=await fetch(n,"navigate"===n.mode?void 0:this._strategy.fetchOptions);for(const n of this.iterateCallbacks("fetchDidSucceed"))t=await n({event:e,request:o,response:t});return t}catch(a){throw r&&await this.runCallbacks("fetchDidFail",{error:a,event:e,originalRequest:r.clone(),request:o.clone()}),a}}async fetchAndCachePut(t){const e=await this.fetch(t),n=e.clone();return this.waitUntil(this.cachePut(t,n)),e}async cacheMatch(t){const e=k(t);let n;const{cacheName:r,matchOptions:o}=this._strategy,i=await this.getCacheKey(e,"read"),a={...o,cacheName:r};n=await caches.match(i,a);for(const c of this.iterateCallbacks("cachedResponseWillBeUsed"))n=await c({cacheName:r,matchOptions:o,cachedResponse:n,request:i,event:this.event})||void 0;return n}async cachePut(t,e){const n=k(t);await N(0);const r=await this.getCacheKey(n,"write");if(!e)throw new b("cache-put-with-no-response",{url:_(r.url)});const o=await this._ensureResponseSafeToCache(e);if(!o)return!1;const{cacheName:i,matchOptions:a}=this._strategy,c=await self.caches.open(i),s=this.hasCallback("cacheDidUpdate"),u=s?await R(c,r.clone(),["__WB_REVISION__"],a):null;try{await c.put(r,s?o.clone():o)}catch(l){throw"QuotaExceededError"===l.name&&await P(),l}for(const f of this.iterateCallbacks("cacheDidUpdate"))await f({cacheName:i,oldResponse:u,newResponse:o.clone(),request:r,event:this.event});return!0}async getCacheKey(t,e){if(!this._cacheKeys[e]){let n=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))n=k(await t({mode:e,request:n,event:this.event,params:this.params}));this._cacheKeys[e]=n}return this._cacheKeys[e]}hasCallback(t){for(const e of this._strategy.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const n of this.iterateCallbacks(t))await n(e)}*iterateCallbacks(t){for(const e of this._strategy.plugins)if("function"===typeof e[t]){const n=this._pluginStateMap.get(e),r=r=>{const o={...r,state:n};return e[t](o)};yield r}}waitUntil(t){return this._extendLifetimePromises.push(t),t}async doneWaiting(){let t;while(t=this._extendLifetimePromises.shift())await t}destroy(){this._handlerDeferred.resolve()}async _ensureResponseSafeToCache(t){let e=t,n=!1;for(const r of this.iterateCallbacks("cacheWillUpdate"))if(e=await r({request:this.request,response:e,event:this.event})||void 0,n=!0,!e)break;return n||e&&200!==e.status&&(e=void 0),e}}class T{constructor(t={}){this.cacheName=v.getRuntimeName(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,n="string"===typeof t.request?new Request(t.request):t.request,r="params"in t?t.params:void 0,o=new j(this,{event:e,request:n,params:r}),i=this._getResponse(o,n,e),a=this._awaitComplete(i,o,n,e);return[i,a]}async _getResponse(t,e,n){await t.runCallbacks("handlerWillStart",{event:n,request:e});let r=void 0;try{if(r=await this._handle(e,t),!r||"error"===r.type)throw new b("no-response",{url:e.url})}catch(o){for(const i of t.iterateCallbacks("handlerDidError"))if(r=await i({error:o,event:n,request:e}),r)break;if(!r)throw o}for(const i of t.iterateCallbacks("handlerWillRespond"))r=await i({event:n,request:e,response:r});return r}async _awaitComplete(t,e,n,r){let o,i;try{o=await t}catch(i){}try{await e.runCallbacks("handlerDidRespond",{event:r,request:n,response:o}),await e.doneWaiting()}catch(a){i=a}if(await e.runCallbacks("handlerDidComplete",{event:r,request:n,response:o,error:i}),e.destroy(),i)throw i}}class C extends T{constructor(t={}){t.cacheName=f.getPrecacheName(t.cacheName),super(t),this._fallbackToNetwork=!1!==t.fallbackToNetwork,this.plugins.push(C.copyRedirectedCacheableResponsesPlugin)}async _handle(t,e){const n=await e.cacheMatch(t);return n||(e.event&&"install"===e.event.type?await this._handleInstall(t,e):await this._handleFetch(t,e))}async _handleFetch(t,e){let n;if(!this._fallbackToNetwork)throw new c("missing-precache-entry",{cacheName:this.cacheName,url:t.url});return n=await e.fetch(t),n}async _handleInstall(t,e){this._useDefaultCacheabilityPluginIfNeeded();const n=await e.fetch(t),r=await e.cachePut(t,n.clone());if(!r)throw new c("bad-precaching-response",{url:t.url,status:n.status});return n}_useDefaultCacheabilityPluginIfNeeded(){let t=null,e=0;for(const[n,r]of this.plugins.entries())r!==C.copyRedirectedCacheableResponsesPlugin&&(r===C.defaultPrecacheCacheabilityPlugin&&(t=n),r.cacheWillUpdate&&e++);0===e?this.plugins.push(C.defaultPrecacheCacheabilityPlugin):e>1&&null!==t&&this.plugins.splice(t,1)}}C.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:t}){return!t||t.status>=400?null:t}},C.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:t}){return t.redirected?await d(t):t}};n("95a8");const A=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},q=A;class L extends Error{constructor(t,e){const n=q(t,e);super(n),this.name=t,this.details=e}}n("e6d2");const M="GET",U=t=>t&&"object"===typeof t?t:{handle:t};class I{constructor(t,e,n=M){this.handler=U(e),this.match=t,this.method=n}setCatchHandler(t){this.catchHandler=U(t)}}class D extends I{constructor(t,e,n){const r=({url:e})=>{const n=t.exec(e.href);if(n&&(e.origin===location.origin||0===n.index))return n.slice(1)};super(r,e,n)}}class F{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener("fetch",t=>{const{request:e}=t,n=this.handleRequest({request:e,event:t});n&&t.respondWith(n)})}addCacheListener(){self.addEventListener("message",t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data;0;const n=Promise.all(e.urlsToCache.map(e=>{"string"===typeof e&&(e=[e]);const n=new Request(...e);return this.handleRequest({request:n,event:t})}));t.waitUntil(n),t.ports&&t.ports[0]&&n.then(()=>t.ports[0].postMessage(!0))}})}handleRequest({request:t,event:e}){const n=new URL(t.url,location.href);if(!n.protocol.startsWith("http"))return void 0;const r=n.origin===location.origin,{params:o,route:i}=this.findMatchingRoute({event:e,request:t,sameOrigin:r,url:n});let a=i&&i.handler;const c=t.method;if(!a&&this._defaultHandlerMap.has(c)&&(a=this._defaultHandlerMap.get(c)),!a)return void 0;let s;try{s=a.handle({url:n,request:t,event:e,params:o})}catch(l){s=Promise.reject(l)}const u=i&&i.catchHandler;return s instanceof Promise&&(this._catchHandler||u)&&(s=s.catch(async r=>{if(u){0;try{return await u.handle({url:n,request:t,event:e,params:o})}catch(i){r=i}}if(this._catchHandler)return this._catchHandler.handle({url:n,request:t,event:e});throw r})),s}findMatchingRoute({url:t,sameOrigin:e,request:n,event:r}){const o=this._routes.get(n.method)||[];for(const i of o){let o;const a=i.match({url:t,sameOrigin:e,request:n,event:r});if(a)return o=a,(Array.isArray(a)&&0===a.length||a.constructor===Object&&0===Object.keys(a).length||"boolean"===typeof a)&&(o=void 0),{route:i,params:o}}return{}}setDefaultHandler(t,e=M){this._defaultHandlerMap.set(e,U(t))}setCatchHandler(t){this._catchHandler=U(t)}registerRoute(t){this._routes.has(t.method)||this._routes.set(t.method,[]),this._routes.get(t.method).push(t)}unregisterRoute(t){if(!this._routes.has(t.method))throw new L("unregister-route-but-not-found-with-method",{method:t.method});const e=this._routes.get(t.method).indexOf(t);if(!(e>-1))throw new L("unregister-route-route-not-registered");this._routes.get(t.method).splice(e,1)}}let W;const H=()=>(W||(W=new F,W.addFetchListener(),W.addCacheListener()),W);function K(t,e,n){let r;if("string"===typeof t){const o=new URL(t,location.href);0;const i=({url:t})=>t.href===o.href;r=new I(i,e,n)}else if(t instanceof RegExp)r=new D(t,e,n);else if("function"===typeof t)r=new I(t,e,n);else{if(!(t instanceof I))throw new L("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});r=t}const o=H();return o.registerRoute(r),r}function G(t){const e=H();e.setCatchHandler(t)}class B extends T{async _handle(t,e){let n,r=await e.cacheMatch(t);if(r)0;else{0;try{r=await e.fetchAndCachePut(t)}catch(o){n=o}0}if(!r)throw new b("no-response",{url:t.url,error:n});return r}}const Y={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null};class $ extends T{constructor(t={}){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(Y),this._networkTimeoutSeconds=t.networkTimeoutSeconds||0}async _handle(t,e){const n=[];const r=[];let o;if(this._networkTimeoutSeconds){const{id:i,promise:a}=this._getTimeoutPromise({request:t,logs:n,handler:e});o=i,r.push(a)}const i=this._getNetworkPromise({timeoutId:o,request:t,logs:n,handler:e});r.push(i);const a=await e.waitUntil((async()=>await e.waitUntil(Promise.race(r))||await i)());if(!a)throw new b("no-response",{url:t.url});return a}_getTimeoutPromise({request:t,logs:e,handler:n}){let r;const o=new Promise(e=>{const o=async()=>{e(await n.cacheMatch(t))};r=setTimeout(o,1e3*this._networkTimeoutSeconds)});return{promise:o,id:r}}async _getNetworkPromise({timeoutId:t,request:e,logs:n,handler:r}){let o,i;try{i=await r.fetchAndCachePut(e)}catch(a){o=a}return t&&clearTimeout(t),!o&&i||(i=await r.cacheMatch(e)),i}}class z extends T{constructor(t){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(Y)}async _handle(t,e){const n=e.fetchAndCachePut(t).catch(()=>{});let r,o=await e.cacheMatch(t);if(o)0;else{0;try{o=await n}catch(i){r=i}}if(!o)throw new b("no-response",{url:t.url,error:r});return o}}n("d2e2");const J=(t,...e)=>{let n=t;return e.length>0&&(n+=" :: "+JSON.stringify(e)),n},Q=J;class V extends Error{constructor(t,e){const n=Q(t,e);super(n),this.name=t,this.details=e}}function X(t){t.then(()=>{})}class Z{constructor(t,e,{onupgradeneeded:n,onversionchange:r}={}){this._db=null,this._name=t,this._version=e,this._onupgradeneeded=n,this._onversionchange=r||(()=>this.close())}get db(){return this._db}async open(){if(!this._db)return this._db=await new Promise((t,e)=>{let n=!1;setTimeout(()=>{n=!0,e(new Error("The open request was blocked and timed out"))},this.OPEN_TIMEOUT);const r=indexedDB.open(this._name,this._version);r.onerror=()=>e(r.error),r.onupgradeneeded=t=>{n?(r.transaction.abort(),r.result.close()):"function"===typeof this._onupgradeneeded&&this._onupgradeneeded(t)},r.onsuccess=()=>{const e=r.result;n?e.close():(e.onversionchange=this._onversionchange.bind(this),t(e))}}),this}async getKey(t,e){return(await this.getAllKeys(t,e,1))[0]}async getAll(t,e,n){return await this.getAllMatching(t,{query:e,count:n})}async getAllKeys(t,e,n){const r=await this.getAllMatching(t,{query:e,count:n,includeKeys:!0});return r.map(t=>t.key)}async getAllMatching(t,{index:e,query:n=null,direction:r="next",count:o,includeKeys:i=!1}={}){return await this.transaction([t],"readonly",(a,c)=>{const s=a.objectStore(t),u=e?s.index(e):s,l=[],f=u.openCursor(n,r);f.onsuccess=()=>{const t=f.result;t?(l.push(i?t:t.value),o&&l.length>=o?c(l):t.continue()):c(l)}})}async transaction(t,e,n){return await this.open(),await new Promise((r,o)=>{const i=this._db.transaction(t,e);i.onabort=()=>o(i.error),i.oncomplete=()=>r(),n(i,t=>r(t))})}async _call(t,e,n,...r){const o=(n,o)=>{const i=n.objectStore(e),a=i[t].apply(i,r);a.onsuccess=()=>o(a.result)};return await this.transaction([e],n,o)}close(){this._db&&(this._db.close(),this._db=null)}}Z.prototype.OPEN_TIMEOUT=2e3;const tt={readonly:["get","count","getKey","getAll","getAllKeys"],readwrite:["add","put","clear","delete"]};for(const[yt,mt]of Object.entries(tt))for(const t of mt)t in IDBObjectStore.prototype&&(Z.prototype[t]=async function(e,...n){return await this._call(t,e,yt,...n)});const et=async t=>{await new Promise((e,n)=>{const r=indexedDB.deleteDatabase(t);r.onerror=()=>{n(r.error)},r.onblocked=()=>{n(new Error("Delete blocked"))},r.onsuccess=()=>{e()}})};n("d8a5");const nt="workbox-expiration",rt="cache-entries",ot=t=>{const e=new URL(t,location.href);return e.hash="",e.href};class it{constructor(t){this._cacheName=t,this._db=new Z(nt,1,{onupgradeneeded:t=>this._handleUpgrade(t)})}_handleUpgrade(t){const e=t.target.result,n=e.createObjectStore(rt,{keyPath:"id"});n.createIndex("cacheName","cacheName",{unique:!1}),n.createIndex("timestamp","timestamp",{unique:!1}),et(this._cacheName)}async setTimestamp(t,e){t=ot(t);const n={url:t,timestamp:e,cacheName:this._cacheName,id:this._getId(t)};await this._db.put(rt,n)}async getTimestamp(t){const e=await this._db.get(rt,this._getId(t));return e.timestamp}async expireEntries(t,e){const n=await this._db.transaction(rt,"readwrite",(n,r)=>{const o=n.objectStore(rt),i=o.index("timestamp").openCursor(null,"prev"),a=[];let c=0;i.onsuccess=()=>{const n=i.result;if(n){const r=n.value;r.cacheName===this._cacheName&&(t&&r.timestamp=e?a.push(n.value):c++),n.continue()}else r(a)}}),r=[];for(const o of n)await this._db.delete(rt,o.id),r.push(o.url);return r}_getId(t){return this._cacheName+"|"+ot(t)}}class at{constructor(t,e={}){this._isRunning=!1,this._rerunRequested=!1,this._maxEntries=e.maxEntries,this._maxAgeSeconds=e.maxAgeSeconds,this._matchOptions=e.matchOptions,this._cacheName=t,this._timestampModel=new it(t)}async expireEntries(){if(this._isRunning)return void(this._rerunRequested=!0);this._isRunning=!0;const t=this._maxAgeSeconds?Date.now()-1e3*this._maxAgeSeconds:0,e=await this._timestampModel.expireEntries(t,this._maxEntries),n=await self.caches.open(this._cacheName);for(const r of e)await n.delete(r,this._matchOptions);this._isRunning=!1,this._rerunRequested&&(this._rerunRequested=!1,X(this.expireEntries()))}async updateTimestamp(t){await this._timestampModel.setTimestamp(t,Date.now())}async isURLExpired(t){if(this._maxAgeSeconds){const e=await this._timestampModel.getTimestamp(t),n=Date.now()-1e3*this._maxAgeSeconds;return e[ct.prefix,t,ct.suffix].filter(t=>t&&t.length>0).join("-"),ut=t=>{for(const e of Object.keys(ct))t(e)},lt={updateDetails:t=>{ut(e=>{"string"===typeof t[e]&&(ct[e]=t[e])})},getGoogleAnalyticsName:t=>t||st(ct.googleAnalytics),getPrecacheName:t=>t||st(ct.precache),getPrefix:()=>ct.prefix,getRuntimeName:t=>t||st(ct.runtime),getSuffix:()=>ct.suffix},ft=new Set;function ht(t){ft.add(t)}class pt{constructor(t={}){this.cachedResponseWillBeUsed=async({event:t,request:e,cacheName:n,cachedResponse:r})=>{if(!r)return null;const o=this._isResponseDateFresh(r),i=this._getCacheExpiration(n);X(i.expireEntries());const a=i.updateTimestamp(e.url);if(t)try{t.waitUntil(a)}catch(c){0}return o?r:null},this.cacheDidUpdate=async({cacheName:t,request:e})=>{const n=this._getCacheExpiration(t);await n.updateTimestamp(e.url),await n.expireEntries()},this._config=t,this._maxAgeSeconds=t.maxAgeSeconds,this._cacheExpirations=new Map,t.purgeOnQuotaError&&ht(()=>this.deleteCacheAndMetadata())}_getCacheExpiration(t){if(t===lt.getRuntimeName())throw new V("expire-custom-caches-only");let e=this._cacheExpirations.get(t);return e||(e=new at(t,this._config),this._cacheExpirations.set(t,e)),e}_isResponseDateFresh(t){if(!this._maxAgeSeconds)return!0;const e=this._getDateHeaderTimestamp(t);if(null===e)return!0;const n=Date.now();return e>=n-1e3*this._maxAgeSeconds}_getDateHeaderTimestamp(t){if(!t.headers.has("date"))return null;const e=t.headers.get("date"),n=new Date(e),r=n.getTime();return isNaN(r)?null:r}async deleteCacheAndMetadata(){for(const[t,e]of this._cacheExpirations)await self.caches.delete(t),await e.delete();this._cacheExpirations=new Map}}var dt="offline-html",gt="/offline/";self.addEventListener("install",function(){var t=o(regeneratorRuntime.mark((function t(e){return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:e.waitUntil(caches.open(dt).then((function(t){return t.add(new Request(gt,{cache:"reload"}))})));case 1:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}()),[{'url':'static/vue/css/chunk-vendors.css'},{'url':'static/vue/import_response_view.html'},{'url':'static/vue/js/chunk-vendors.js'},{'url':'static/vue/js/import_response_view.js'},{'url':'static/vue/js/offline_view.js'},{'url':'static/vue/js/recipe_view.js'},{'url':'static/vue/manifest.json'},{'url':'static/vue/offline_view.html'},{'url':'static/vue/recipe_view.html'}],G((function(t){var e=t.event;switch(e.request.destination){case"document":return console.log("Triggered fallback HTML"),caches.open(dt).then((function(t){return t.match(gt)}));default:return console.log("Triggered response ERROR"),Response.error()}})),K((function(t){var e=t.request;return"image"===e.destination}),new B({cacheName:"images",plugins:[new pt({maxEntries:20})]})),K((function(t){var e=t.request;return"script"===e.destination||"style"===e.destination}),new z({cacheName:"assets"})),K(new RegExp("jsreverse"),new z({cacheName:"assets"})),K(new RegExp("jsi18n"),new z({cacheName:"assets"})),K(new RegExp("api/recipe/([0-9]+)"),new $({cacheName:"api-recipe",plugins:[new pt({maxEntries:50})]})),K(new RegExp("api/*"),new $({cacheName:"api",plugins:[new pt({maxEntries:50})]})),K((function(t){var e=t.request;return"document"===e.destination}),new $({cacheName:"html",plugins:[new pt({maxAgeSeconds:2592e3,maxEntries:50})]}))},"25f0":function(t,e,n){"use strict";var r=n("6eeb"),o=n("825a"),i=n("d039"),a=n("ad6d"),c="toString",s=RegExp.prototype,u=s[c],l=i((function(){return"/a/b"!=u.call({source:"a",flags:"b"})})),f=u.name!=c;(l||f)&&r(RegExp.prototype,c,(function(){var t=o(this),e=String(t.source),n=t.flags,r=String(void 0===n&&t instanceof RegExp&&!("flags"in s)?a.call(t):n);return"/"+e+"/"+r}),{unsafe:!0})},2626:function(t,e,n){"use strict";var r=n("d066"),o=n("9bf2"),i=n("b622"),a=n("83ab"),c=i("species");t.exports=function(t){var e=r(t),n=o.f;a&&e&&!e[c]&&n(e,c,{configurable:!0,get:function(){return this}})}},"2d00":function(t,e,n){var r,o,i=n("da84"),a=n("342f"),c=i.process,s=c&&c.versions,u=s&&s.v8;u?(r=u.split("."),o=r[0]+r[1]):a&&(r=a.match(/Edge\/(\d+)/),(!r||r[1]>=74)&&(r=a.match(/Chrome\/(\d+)/),r&&(o=r[1]))),t.exports=o&&+o},"342f":function(t,e,n){var r=n("d066");t.exports=r("navigator","userAgent")||""},"3bbe":function(t,e,n){var r=n("861d");t.exports=function(t){if(!r(t)&&null!==t)throw TypeError("Can't set "+String(t)+" as a prototype");return t}},"40b9":function(t,e,n){"use strict";try{self["workbox:core:6.1.2"]&&_()}catch(r){}},"428f":function(t,e,n){var r=n("da84");t.exports=r},"44ad":function(t,e,n){var r=n("d039"),o=n("c6b6"),i="".split;t.exports=r((function(){return!Object("z").propertyIsEnumerable(0)}))?function(t){return"String"==o(t)?i.call(t,""):Object(t)}:Object},"44e7":function(t,e,n){var r=n("861d"),o=n("c6b6"),i=n("b622"),a=i("match");t.exports=function(t){var e;return r(t)&&(void 0!==(e=t[a])?!!e:"RegExp"==o(t))}},"466d":function(t,e,n){"use strict";var r=n("d784"),o=n("825a"),i=n("50c4"),a=n("1d80"),c=n("8aa5"),s=n("14c3");r("match",1,(function(t,e,n){return[function(e){var n=a(this),r=void 0==e?void 0:e[t];return void 0!==r?r.call(e,n):new RegExp(e)[t](String(n))},function(t){var r=n(e,t,this);if(r.done)return r.value;var a=o(t),u=String(this);if(!a.global)return s(a,u);var l=a.unicode;a.lastIndex=0;var f,h=[],p=0;while(null!==(f=s(a,u))){var d=String(f[0]);h[p]=d,""===d&&(a.lastIndex=c(u,i(a.lastIndex),l)),p++}return 0===p?null:h}]}))},4930:function(t,e,n){var r=n("605d"),o=n("2d00"),i=n("d039");t.exports=!!Object.getOwnPropertySymbols&&!i((function(){return!Symbol.sham&&(r?38===o:o>37&&o<41)}))},"4d63":function(t,e,n){var r=n("83ab"),o=n("da84"),i=n("94ca"),a=n("7156"),c=n("9bf2").f,s=n("241c").f,u=n("44e7"),l=n("ad6d"),f=n("9f7f"),h=n("6eeb"),p=n("d039"),d=n("69f3").set,g=n("2626"),y=n("b622"),m=y("match"),v=o.RegExp,w=v.prototype,x=/a/g,b=/a/g,_=new v(x)!==x,E=f.UNSUPPORTED_Y,R=r&&i("RegExp",!_||E||p((function(){return b[m]=!1,v(x)!=x||v(b)==b||"/a/i"!=v(x,"i")})));if(R){var S=function(t,e){var n,r=this instanceof S,o=u(t),i=void 0===e;if(!r&&o&&t.constructor===S&&i)return t;_?o&&!i&&(t=t.source):t instanceof S&&(i&&(e=l.call(t)),t=t.source),E&&(n=!!e&&e.indexOf("y")>-1,n&&(e=e.replace(/y/g,"")));var c=a(_?new v(t,e):v(t,e),r?this:w,S);return E&&n&&d(c,{sticky:n}),c},O=function(t){t in S||c(S,t,{configurable:!0,get:function(){return v[t]},set:function(e){v[t]=e}})},P=s(v),N=0;while(P.length>N)O(P[N++]);w.constructor=S,S.prototype=w,h(o,"RegExp",S)}g("RegExp")},"4d64":function(t,e,n){var r=n("fc6a"),o=n("50c4"),i=n("23cb"),a=function(t){return function(e,n,a){var c,s=r(e),u=o(s.length),l=i(a,u);if(t&&n!=n){while(u>l)if(c=s[l++],c!=c)return!0}else for(;u>l;l++)if((t||l in s)&&s[l]===n)return t||l||0;return!t&&-1}};t.exports={includes:a(!0),indexOf:a(!1)}},"50c4":function(t,e,n){var r=n("a691"),o=Math.min;t.exports=function(t){return t>0?o(r(t),9007199254740991):0}},5135:function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},5692:function(t,e,n){var r=n("c430"),o=n("c6cd");(t.exports=function(t,e){return o[t]||(o[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.9.1",mode:r?"pure":"global",copyright:"© 2021 Denis Pushkarev (zloirock.ru)"})},"56ef":function(t,e,n){var r=n("d066"),o=n("241c"),i=n("7418"),a=n("825a");t.exports=r("Reflect","ownKeys")||function(t){var e=o.f(a(t)),n=i.f;return n?e.concat(n(t)):e}},"5c6c":function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},"605d":function(t,e,n){var r=n("c6b6"),o=n("da84");t.exports="process"==r(o.process)},6547:function(t,e,n){var r=n("a691"),o=n("1d80"),i=function(t){return function(e,n){var i,a,c=String(o(e)),s=r(n),u=c.length;return s<0||s>=u?t?"":void 0:(i=c.charCodeAt(s),i<55296||i>56319||s+1===u||(a=c.charCodeAt(s+1))<56320||a>57343?t?c.charAt(s):i:t?c.slice(s,s+2):a-56320+(i-55296<<10)+65536)}};t.exports={codeAt:i(!1),charAt:i(!0)}},"69f3":function(t,e,n){var r,o,i,a=n("7f9a"),c=n("da84"),s=n("861d"),u=n("9112"),l=n("5135"),f=n("c6cd"),h=n("f772"),p=n("d012"),d=c.WeakMap,g=function(t){return i(t)?o(t):r(t,{})},y=function(t){return function(e){var n;if(!s(e)||(n=o(e)).type!==t)throw TypeError("Incompatible receiver, "+t+" required");return n}};if(a){var m=f.state||(f.state=new d),v=m.get,w=m.has,x=m.set;r=function(t,e){return e.facade=t,x.call(m,t,e),e},o=function(t){return v.call(m,t)||{}},i=function(t){return w.call(m,t)}}else{var b=h("state");p[b]=!0,r=function(t,e){return e.facade=t,u(t,b,e),e},o=function(t){return l(t,b)?t[b]:{}},i=function(t){return l(t,b)}}t.exports={set:r,get:o,has:i,enforce:g,getterFor:y}},"6aa8":function(t,e,n){"use strict";try{self["workbox:strategies:6.1.2"]&&_()}catch(r){}},"6eeb":function(t,e,n){var r=n("da84"),o=n("9112"),i=n("5135"),a=n("ce4e"),c=n("8925"),s=n("69f3"),u=s.get,l=s.enforce,f=String(String).split("String");(t.exports=function(t,e,n,c){var s,u=!!c&&!!c.unsafe,h=!!c&&!!c.enumerable,p=!!c&&!!c.noTargetGet;"function"==typeof n&&("string"!=typeof e||i(n,"name")||o(n,"name",e),s=l(n),s.source||(s.source=f.join("string"==typeof e?e:""))),t!==r?(u?!p&&t[e]&&(h=!0):delete t[e],h?t[e]=n:o(t,e,n)):h?t[e]=n:a(e,n)})(Function.prototype,"toString",(function(){return"function"==typeof this&&u(this).source||c(this)}))},7156:function(t,e,n){var r=n("861d"),o=n("d2bb");t.exports=function(t,e,n){var i,a;return o&&"function"==typeof(i=e.constructor)&&i!==n&&r(a=i.prototype)&&a!==n.prototype&&o(t,a),t}},7418:function(t,e){e.f=Object.getOwnPropertySymbols},"741b":function(t,e,n){"use strict";try{self["workbox:core:6.1.2"]&&_()}catch(r){}},7839:function(t,e){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},"7f9a":function(t,e,n){var r=n("da84"),o=n("8925"),i=r.WeakMap;t.exports="function"===typeof i&&/native code/.test(o(i))},"825a":function(t,e,n){var r=n("861d");t.exports=function(t){if(!r(t))throw TypeError(String(t)+" is not an object");return t}},"83ab":function(t,e,n){var r=n("d039");t.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},"861d":function(t,e){t.exports=function(t){return"object"===typeof t?null!==t:"function"===typeof t}},8925:function(t,e,n){var r=n("c6cd"),o=Function.toString;"function"!=typeof r.inspectSource&&(r.inspectSource=function(t){return o.call(t)}),t.exports=r.inspectSource},"8aa5":function(t,e,n){"use strict";var r=n("6547").charAt;t.exports=function(t,e,n){return e+(n?r(t,e).length:1)}},"90e3":function(t,e){var n=0,r=Math.random();t.exports=function(t){return"Symbol("+String(void 0===t?"":t)+")_"+(++n+r).toString(36)}},9112:function(t,e,n){var r=n("83ab"),o=n("9bf2"),i=n("5c6c");t.exports=r?function(t,e,n){return o.f(t,e,i(1,n))}:function(t,e,n){return t[e]=n,t}},9263:function(t,e,n){"use strict";var r=n("ad6d"),o=n("9f7f"),i=RegExp.prototype.exec,a=String.prototype.replace,c=i,s=function(){var t=/a/,e=/b*/g;return i.call(t,"a"),i.call(e,"a"),0!==t.lastIndex||0!==e.lastIndex}(),u=o.UNSUPPORTED_Y||o.BROKEN_CARET,l=void 0!==/()??/.exec("")[1],f=s||l||u;f&&(c=function(t){var e,n,o,c,f=this,h=u&&f.sticky,p=r.call(f),d=f.source,g=0,y=t;return h&&(p=p.replace("y",""),-1===p.indexOf("g")&&(p+="g"),y=String(t).slice(f.lastIndex),f.lastIndex>0&&(!f.multiline||f.multiline&&"\n"!==t[f.lastIndex-1])&&(d="(?: "+d+")",y=" "+y,g++),n=new RegExp("^(?:"+d+")",p)),l&&(n=new RegExp("^"+d+"$(?!\\s)",p)),s&&(e=f.lastIndex),o=i.call(h?n:f,y),h?o?(o.input=o.input.slice(g),o[0]=o[0].slice(g),o.index=f.lastIndex,f.lastIndex+=o[0].length):f.lastIndex=0:s&&o&&(f.lastIndex=f.global?o.index+o[0].length:e),l&&o&&o.length>1&&a.call(o[0],n,(function(){for(c=1;c=0;--i){var a=this.tryEntries[i],c=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var s=r.call(a,"catchLoc"),u=r.call(a,"finallyLoc");if(s&&u){if(this.prev=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&r.call(o,"finallyLoc")&&this.prev=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),N(n),g}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var r=n.completion;if("throw"===r.type){var o=r.arg;N(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,n,r){return this.delegate={iterator:j(t),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=e),g}},t}(t.exports);try{regeneratorRuntime=r}catch(o){Function("r","regeneratorRuntime = r")(r)}},"9bf2":function(t,e,n){var r=n("83ab"),o=n("0cfb"),i=n("825a"),a=n("c04e"),c=Object.defineProperty;e.f=r?c:function(t,e,n){if(i(t),e=a(e,!0),i(n),o)try{return c(t,e,n)}catch(r){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(t[e]=n.value),t}},"9f7f":function(t,e,n){"use strict";var r=n("d039");function o(t,e){return RegExp(t,e)}e.UNSUPPORTED_Y=r((function(){var t=o("a","y");return t.lastIndex=2,null!=t.exec("abcd")})),e.BROKEN_CARET=r((function(){var t=o("^r","gy");return t.lastIndex=2,null!=t.exec("str")}))},a691:function(t,e){var n=Math.ceil,r=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?r:n)(t)}},ac1f:function(t,e,n){"use strict";var r=n("23e7"),o=n("9263");r({target:"RegExp",proto:!0,forced:/./.exec!==o},{exec:o})},ad6d:function(t,e,n){"use strict";var r=n("825a");t.exports=function(){var t=r(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.dotAll&&(e+="s"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},b041:function(t,e,n){"use strict";var r=n("00ee"),o=n("f5df");t.exports=r?{}.toString:function(){return"[object "+o(this)+"]"}},b622:function(t,e,n){var r=n("da84"),o=n("5692"),i=n("5135"),a=n("90e3"),c=n("4930"),s=n("fdbf"),u=o("wks"),l=r.Symbol,f=s?l:l&&l.withoutSetter||a;t.exports=function(t){return i(u,t)&&(c||"string"==typeof u[t])||(c&&i(l,t)?u[t]=l[t]:u[t]=f("Symbol."+t)),u[t]}},c04e:function(t,e,n){var r=n("861d");t.exports=function(t,e){if(!r(t))return t;var n,o;if(e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;if("function"==typeof(n=t.valueOf)&&!r(o=n.call(t)))return o;if(!e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;throw TypeError("Can't convert object to primitive value")}},c430:function(t,e){t.exports=!1},c6b6:function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},c6cd:function(t,e,n){var r=n("da84"),o=n("ce4e"),i="__core-js_shared__",a=r[i]||o(i,{});t.exports=a},c700:function(t,e,n){"use strict";try{self["workbox:precaching:6.1.2"]&&_()}catch(r){}},c8ba:function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(r){"object"===typeof window&&(n=window)}t.exports=n},ca84:function(t,e,n){var r=n("5135"),o=n("fc6a"),i=n("4d64").indexOf,a=n("d012");t.exports=function(t,e){var n,c=o(t),s=0,u=[];for(n in c)!r(a,n)&&r(c,n)&&u.push(n);while(e.length>s)r(c,n=e[s++])&&(~i(u,n)||u.push(n));return u}},cc12:function(t,e,n){var r=n("da84"),o=n("861d"),i=r.document,a=o(i)&&o(i.createElement);t.exports=function(t){return a?i.createElement(t):{}}},ce4e:function(t,e,n){var r=n("da84"),o=n("9112");t.exports=function(t,e){try{o(r,t,e)}catch(n){r[t]=e}return e}},d012:function(t,e){t.exports={}},d039:function(t,e){t.exports=function(t){try{return!!t()}catch(e){return!0}}},d066:function(t,e,n){var r=n("428f"),o=n("da84"),i=function(t){return"function"==typeof t?t:void 0};t.exports=function(t,e){return arguments.length<2?i(r[t])||i(o[t]):r[t]&&r[t][e]||o[t]&&o[t][e]}},d1e7:function(t,e,n){"use strict";var r={}.propertyIsEnumerable,o=Object.getOwnPropertyDescriptor,i=o&&!r.call({1:2},1);e.f=i?function(t){var e=o(this,t);return!!e&&e.enumerable}:r},d2bb:function(t,e,n){var r=n("825a"),o=n("3bbe");t.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,n={};try{t=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set,t.call(n,[]),e=n instanceof Array}catch(i){}return function(n,i){return r(n),o(i),e?t.call(n,i):n.__proto__=i,n}}():void 0)},d2e2:function(t,e,n){"use strict";try{self["workbox:core:6.1.2"]&&_()}catch(r){}},d3b7:function(t,e,n){var r=n("00ee"),o=n("6eeb"),i=n("b041");r||o(Object.prototype,"toString",i,{unsafe:!0})},d784:function(t,e,n){"use strict";n("ac1f");var r=n("6eeb"),o=n("d039"),i=n("b622"),a=n("9263"),c=n("9112"),s=i("species"),u=!o((function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")})),l=function(){return"$0"==="a".replace(/./,"$0")}(),f=i("replace"),h=function(){return!!/./[f]&&""===/./[f]("a","$0")}(),p=!o((function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var n="ab".split(t);return 2!==n.length||"a"!==n[0]||"b"!==n[1]}));t.exports=function(t,e,n,f){var d=i(t),g=!o((function(){var e={};return e[d]=function(){return 7},7!=""[t](e)})),y=g&&!o((function(){var e=!1,n=/a/;return"split"===t&&(n={},n.constructor={},n.constructor[s]=function(){return n},n.flags="",n[d]=/./[d]),n.exec=function(){return e=!0,null},n[d](""),!e}));if(!g||!y||"replace"===t&&(!u||!l||h)||"split"===t&&!p){var m=/./[d],v=n(d,""[t],(function(t,e,n,r,o){return e.exec===a?g&&!o?{done:!0,value:m.call(e,n,r)}:{done:!0,value:t.call(n,e,r)}:{done:!1}}),{REPLACE_KEEPS_$0:l,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:h}),w=v[0],x=v[1];r(String.prototype,t,w),r(RegExp.prototype,d,2==e?function(t,e){return x.call(t,this,e)}:function(t){return x.call(t,this)})}f&&c(RegExp.prototype[d],"sham",!0)}},d8a5:function(t,e,n){"use strict";try{self["workbox:expiration:6.1.2"]&&_()}catch(r){}},da84:function(t,e,n){(function(e){var n=function(t){return t&&t.Math==Math&&t};t.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof e&&e)||function(){return this}()||Function("return this")()}).call(this,n("c8ba"))},e6d2:function(t,e,n){"use strict";try{self["workbox:routing:6.1.2"]&&_()}catch(r){}},e893:function(t,e,n){var r=n("5135"),o=n("56ef"),i=n("06cf"),a=n("9bf2");t.exports=function(t,e){for(var n=o(e),c=a.f,s=i.f,u=0;u/', import_export.import_response, name='view_import_response'), path('export/', import_export.export_recipe, name='view_export'), path('view/recipe/', views.recipe_view, name='view_recipe'), diff --git a/cookbook/views/import_export.py b/cookbook/views/import_export.py index b067afd5..c19b5cb6 100644 --- a/cookbook/views/import_export.py +++ b/cookbook/views/import_export.py @@ -3,7 +3,9 @@ import threading from io import BytesIO from django.contrib import messages +from django.http import HttpResponseRedirect from django.shortcuts import render +from django.urls import reverse from django.utils.translation import gettext as _ from cookbook.forms import ExportForm, ImportForm, ImportExportBase @@ -48,8 +50,7 @@ def import_recipe(request): t.setDaemon(True) t.start() - messages.add_message(request, messages.SUCCESS, 'Import started') - return render(request, 'import.html', {'form': form}) + return HttpResponseRedirect(reverse('view_import_response', args=[il.pk])) except NotImplementedError: messages.add_message(request, messages.ERROR, _('Importing is not implemented for this provider')) else: @@ -78,3 +79,8 @@ def export_recipe(request): form = ExportForm(initial={'recipes': recipe}, space=request.space) return render(request, 'export.html', {'form': form}) + + +@group_required('user') +def import_response(request, pk): + return render(request, 'import_response.html', {'pk': pk}) diff --git a/vue/src/apps/ImportResponseView/ImportResponseView.vue b/vue/src/apps/ImportResponseView/ImportResponseView.vue new file mode 100644 index 00000000..be403c98 --- /dev/null +++ b/vue/src/apps/ImportResponseView/ImportResponseView.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/vue/src/apps/ImportResponseView/main.js b/vue/src/apps/ImportResponseView/main.js new file mode 100644 index 00000000..1f193b54 --- /dev/null +++ b/vue/src/apps/ImportResponseView/main.js @@ -0,0 +1,8 @@ +import Vue from 'vue' +import App from './ImportResponseView.vue' + +Vue.config.productionTip = false + +new Vue({ + render: h => h(App), +}).$mount('#app') diff --git a/vue/src/utils/api.js b/vue/src/utils/api.js index 3dda8be8..41dc8f84 100644 --- a/vue/src/utils/api.js +++ b/vue/src/utils/api.js @@ -18,6 +18,16 @@ export function apiLoadRecipe(recipe_id) { }) } +export function apiLoadImportLog(id) { + let url = resolveDjangoUrl('api:importlog-detail', id) + + return axios.get(url).then((response) => { + return response.data + }).catch((err) => { + handleError(err, 'There was an error loading a resource!', 'danger') + }) +} + export function apiLogCooking(cook_log) { return axios.post(resolveDjangoUrl('api:cooklog-list',), cook_log).then((response) => { diff --git a/vue/vue.config.js b/vue/vue.config.js index 48ce9581..2cbabfa3 100644 --- a/vue/vue.config.js +++ b/vue/vue.config.js @@ -9,6 +9,10 @@ const pages = { entry: './src/apps/OfflineView/main.js', chunks: ['chunk-vendors'] }, + 'import_response_view': { + entry: './src/apps/ImportResponseView/main.js', + chunks: ['chunk-vendors'] + }, } module.exports = { diff --git a/vue/webpack-stats.json b/vue/webpack-stats.json index f387805d..509f4d0a 100644 --- a/vue/webpack-stats.json +++ b/vue/webpack-stats.json @@ -1 +1 @@ -{"status":"done","chunks":{"chunk-vendors":[{"name":"css/chunk-vendors.css","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\css\\chunk-vendors.css"},{"name":"js/chunk-vendors.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\chunk-vendors.js"}],"offline_view":[{"name":"js/offline_view.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\offline_view.js"}],"recipe_view":[{"name":"js/recipe_view.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\recipe_view.js"}]}} \ No newline at end of file +{"status":"done","chunks":{"chunk-vendors":[{"name":"css/chunk-vendors.css","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\css\\chunk-vendors.css"},{"name":"js/chunk-vendors.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\chunk-vendors.js"}],"import_response_view":[{"name":"js/import_response_view.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\import_response_view.js"}],"offline_view":[{"name":"js/offline_view.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\offline_view.js"}],"recipe_view":[{"name":"js/recipe_view.js","path":"F:\\Developement\\Django\\recipes\\cookbook\\static\\vue\\js\\recipe_view.js"}]}} \ No newline at end of file From 8bfbd96398fa5a458b5132488a8d4e237e90ca60 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 20:24:42 +0100 Subject: [PATCH 95/96] fixed slicing issue --- cookbook/serializer.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 916460a0..76def549 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -44,10 +44,11 @@ class CustomDecimalField(serializers.Field): class SpaceFilterSerializer(serializers.ListSerializer): def to_representation(self, data): - if self.child.Meta.model == User: - data = data.filter(userpreference__space=self.context['request'].space) - else: - data = data.filter(**{'__'.join(data.model.get_space_key()): self.context['request'].space}) + if not data.query.is_sliced: # if query is sliced it came from api request not nested serializer + if self.child.Meta.model == User: + data = data.filter(userpreference__space=self.context['request'].space) + else: + data = data.filter(**{'__'.join(data.model.get_space_key()): self.context['request'].space}) return super().to_representation(data) From 661f7ae789b2b54e6e35050d0bcffb4b899b0b94 Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Thu, 18 Mar 2021 20:34:37 +0100 Subject: [PATCH 96/96] fixed slice fix again --- cookbook/serializer.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 76def549..fe2db438 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -1,6 +1,7 @@ from decimal import Decimal from django.contrib.auth.models import User +from django.db.models import QuerySet from drf_writable_nested import (UniqueFieldsMixin, WritableNestedModelSerializer) from rest_framework import serializers @@ -44,11 +45,13 @@ class CustomDecimalField(serializers.Field): class SpaceFilterSerializer(serializers.ListSerializer): def to_representation(self, data): - if not data.query.is_sliced: # if query is sliced it came from api request not nested serializer - if self.child.Meta.model == User: - data = data.filter(userpreference__space=self.context['request'].space) - else: - data = data.filter(**{'__'.join(data.model.get_space_key()): self.context['request'].space}) + if type(data) == QuerySet and data.query.is_sliced: + # if query is sliced it came from api request not nested serializer + return super().to_representation(data) + if self.child.Meta.model == User: + data = data.filter(userpreference__space=self.context['request'].space) + else: + data = data.filter(**{'__'.join(data.model.get_space_key()): self.context['request'].space}) return super().to_representation(data)