From 5de5d4d612b32b6dbd528b03461be3e2dddbf1ff Mon Sep 17 00:00:00 2001 From: Daniel Brendel Date: Sat, 2 Mar 2024 22:05:34 +0100 Subject: [PATCH] System messages --- .env.example | 2 +- app/controller/admin.php | 2 ++ app/controller/chat.php | 3 +- app/lang/de/app.php | 3 +- app/lang/de/tb.php | 5 +++ app/lang/en/app.php | 3 +- app/lang/en/tb.php | 5 +++ app/migrations/AppModel.php | 1 + app/migrations/ChatMsgModel.php | 1 + app/models/PlantsModel.php | 1 + app/modules/TextBlockModule.php | 52 ++++++++++++++++++++++++++++++ app/resources/js/app.js | 42 ++++++++++++++++++------- app/resources/sass/app.scss | 56 +++++++++++++++++++++++++++++++++ app/views/admin.php | 6 ++++ app/views/chat.php | 46 ++++++++++++++++++--------- public/install/index.php | 2 +- public/js/app.js | 4 +-- 17 files changed, 201 insertions(+), 33 deletions(-) create mode 100644 app/lang/de/tb.php create mode 100644 app/lang/en/tb.php create mode 100644 app/modules/TextBlockModule.php diff --git a/.env.example b/.env.example index fa506f0..9dcbe3d 100644 --- a/.env.example +++ b/.env.example @@ -52,7 +52,7 @@ DB_PASSWORD="" DB_PORT=3306 DB_DATABASE=hortusfox DB_DRIVER=mysql -DB_CHARSET="utf8" +DB_CHARSET="utf8mb4" # SMTP settings SMTP_FROMNAME="Test" diff --git a/app/controller/admin.php b/app/controller/admin.php index 7ae21f1..5242c1f 100644 --- a/app/controller/admin.php +++ b/app/controller/admin.php @@ -69,6 +69,7 @@ class AdminController extends BaseController { $lang = $request->params()->query('lang', app('language')); $scroller = (bool)$request->params()->query('scroller', 0); $enablechat = (bool)$request->params()->query('enablechat', 0); + $enablesysmsgs = (bool)$request->params()->query('enablesysmsgs', 0); $onlinetimelimit = (int)$request->params()->query('onlinetimelimit', app('chat_timelimit')); $chatonlineusers = (bool)$request->params()->query('chatonlineusers', 0); $chattypingindicator = (bool)$request->params()->query('chattypingindicator', 0); @@ -83,6 +84,7 @@ class AdminController extends BaseController { 'language' => $lang, 'scroller' => $scroller, 'chat_enable' => $enablechat, + 'chat_system' => $enablesysmsgs, 'chat_timelimit' => $onlinetimelimit, 'chat_showusers' => $chatonlineusers, 'chat_indicator' => $chattypingindicator, diff --git a/app/controller/chat.php b/app/controller/chat.php index 2b4138b..1ba98a5 100644 --- a/app/controller/chat.php +++ b/app/controller/chat.php @@ -88,8 +88,9 @@ class ChatController extends BaseController { 'userId' => $message->get('userId'), 'userName' => UserModel::getNameById($message->get('userId')), 'message' => $message->get('message'), + 'system' => $message->get('system'), 'chatcolor' => UserModel::getChatColorForUser($message->get('userId')), - 'created_at' => $message->get('created_at'), + 'created_at' => date('Y-m-h H:i', strtotime($message->get('created_at'))), 'diffForHumans' => (new Carbon($message->get('created_at')))->diffForHumans(), ]; } diff --git a/app/lang/de/app.php b/app/lang/de/app.php index 0c849ae..1a08c76 100644 --- a/app/lang/de/app.php +++ b/app/lang/de/app.php @@ -258,5 +258,6 @@ return [ 'import' => 'Importieren', 'import_successful' => 'Erfolgreich importiert!', 'pwa_enable' => 'PWA Unterstützung aktivieren', - 'home' => 'Home' + 'home' => 'Home', + 'chat_system' => 'Systemmeldungen im Chat aktivieren' ]; \ No newline at end of file diff --git a/app/lang/de/tb.php b/app/lang/de/tb.php new file mode 100644 index 0000000..29919e3 --- /dev/null +++ b/app/lang/de/tb.php @@ -0,0 +1,5 @@ + 'Ich habe eine neue Pflanze hinzugefügt: {name}' +]; \ No newline at end of file diff --git a/app/lang/en/app.php b/app/lang/en/app.php index 085639e..674382e 100644 --- a/app/lang/en/app.php +++ b/app/lang/en/app.php @@ -258,5 +258,6 @@ return [ 'import' => 'Import', 'import_successful' => 'Import succeeded!', 'pwa_enable' => 'Enable PWA support', - 'home' => 'Home' + 'home' => 'Home', + 'chat_system' => 'Enable system messages' ]; \ No newline at end of file diff --git a/app/lang/en/tb.php b/app/lang/en/tb.php new file mode 100644 index 0000000..cbdb9db --- /dev/null +++ b/app/lang/en/tb.php @@ -0,0 +1,5 @@ + 'I added a new plant: {name}' +]; \ No newline at end of file diff --git a/app/migrations/AppModel.php b/app/migrations/AppModel.php index 359c7e0..0feb4b2 100644 --- a/app/migrations/AppModel.php +++ b/app/migrations/AppModel.php @@ -35,6 +35,7 @@ class AppModel_Migration { $this->database->add('chat_timelimit INT NOT NULL DEFAULT 5'); $this->database->add('chat_showusers BOOLEAN NOT NULL DEFAULT 1'); $this->database->add('chat_indicator BOOLEAN NOT NULL DEFAULT 1'); + $this->database->add('chat_system BOOLEAN NOT NULL DEFAULT 1'); $this->database->add('history_enable BOOLEAN NOT NULL DEFAULT 1'); $this->database->add('history_name VARCHAR(512) NULL DEFAULT \'History\''); $this->database->add('enable_media_share BOOLEAN NOT NULL DEFAULT 0'); diff --git a/app/migrations/ChatMsgModel.php b/app/migrations/ChatMsgModel.php index 9fb91d5..4140277 100644 --- a/app/migrations/ChatMsgModel.php +++ b/app/migrations/ChatMsgModel.php @@ -30,6 +30,7 @@ class ChatMsgModel_Migration { $this->database->add('id INT NOT NULL AUTO_INCREMENT PRIMARY KEY'); $this->database->add('userId INT NOT NULL'); $this->database->add('message TEXT NOT NULL'); + $this->database->add('system BOOLEAN NOT NULL DEFAULT 0'); $this->database->add('created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP'); $this->database->create(); } diff --git a/app/models/PlantsModel.php b/app/models/PlantsModel.php index b26c952..b4ffe39 100644 --- a/app/models/PlantsModel.php +++ b/app/models/PlantsModel.php @@ -236,6 +236,7 @@ $query = static::raw('SELECT * FROM `' . self::tableName() . '` ORDER BY id DESC LIMIT 1')->first(); + TextBlockModule::newPlant($name, url('/plants/details/' . $query->get('id'))); LogModel::addLog($user->get('id'), $location, 'add_plant', $name, url('/plants/details/' . $query->get('id'))); return $query->get('id'); diff --git a/app/modules/TextBlockModule.php b/app/modules/TextBlockModule.php new file mode 100644 index 0000000..3f36b9f --- /dev/null +++ b/app/modules/TextBlockModule.php @@ -0,0 +1,52 @@ + $name, 'url' => $url]); + + static::addToChat($text, 'x1fab4'); + } catch (\Exception $e) { + throw $e; + } + } + + /** + * @param $message + * @param $icon + * @return void + * @throws \Exception + */ + private static function addToChat($message, $icon) + { + try { + if (!app('chat_system')) { + return; + } + + $user = UserModel::getAuthUser(); + if (!$user) { + throw new \Exception('Invalid user'); + } + + $icon = html_entity_decode('&#' . $icon, ENT_COMPAT | ENT_QUOTES); + + ChatMsgModel::raw('INSERT INTO `' . ChatMsgModel::tableName() . '` (userId, message, system, created_at) VALUES(?, ?, 1, CURRENT_TIMESTAMP)', [ + $user->get('id'), + $icon . ' ' . $message + ]); + } catch (\Exception $e) { + throw $e; + } + } +} diff --git a/app/resources/js/app.js b/app/resources/js/app.js index 466e7d8..0215ea4 100644 --- a/app/resources/js/app.js +++ b/app/resources/js/app.js @@ -413,22 +413,40 @@ window.vue = new Vue({ chatmsgright = 'chat-message-right'; } - let html = ` -
-
-
` + elem.userName + `
-
` + window.vue.newChatMessage + `
+ let html = ''; + + if (!elem.system) { + html = ` +
+
+
` + elem.userName + `
+
` + window.vue.newChatMessage + `
+
+ +
+
` + elem.message + `
+
+ +
+ ` + elem.diffForHumans + ` +
+
+ `; + } else { + html = ` +
+
+
` + elem.userName + ` @ ` + elem.created_at + `
+ +
` + elem.message + `
-
-
` + elem.message + `
-
- -
- ` + elem.diffForHumans + ` +
+
` + window.vue.newChatMessage + `
- `; + `; + } return html; }, diff --git a/app/resources/sass/app.scss b/app/resources/sass/app.scss index 5a24370..3322127 100644 --- a/app/resources/sass/app.scss +++ b/app/resources/sass/app.scss @@ -1362,6 +1362,62 @@ fieldset .field { color: rgb(92, 255, 0); } +.system-message { + position: relative; + background-color: rgb(205, 202, 165); + border-radius: 10px; + padding: 20px; + margin-bottom: 20px; +} + +.system-message-left { + position: relative; + display: inline-block; + width: 93%; + @media screen and (max-width: 1000px) { + width: 80%; + } +} + +.system-message-left-new { + top: -3px; +} + +.system-message-right { + position: relative; + display: inline-block; + top: 3px; +} + +.system-message-context { + position: relative; + display: inline-block; + font-weight: bold; +} + +.system-message-content { + position: relative; + display: inline-block; + @media screen and (max-width: 768px) { + margin-top: 10px; + } +} + +.system-message-content a { + color: rgb(135, 75, 5); +} + +.system-message-content a:hover { + color: rgb(135, 75, 5); + text-decoration: underline; +} + +.system-message-new { + @media screen and (max-width: 768px) { + top: -58px; + } +} + .scroll-to-top { position: fixed; z-index: 102; diff --git a/app/views/admin.php b/app/views/admin.php index 8f50217..0434076 100644 --- a/app/views/admin.php +++ b/app/views/admin.php @@ -64,6 +64,12 @@
+
+
+  {{ __('app.chat_system') }} +
+
+
diff --git a/app/views/chat.php b/app/views/chat.php index 3118c5e..b54adb8 100644 --- a/app/views/chat.php +++ b/app/views/chat.php @@ -34,22 +34,40 @@ @if (isset($messages)) @foreach ($messages as $message) -
-
-
{{ UserModel::getNameById($message->get('userId')) }}
- @if (ChatViewModel::handleNewMessage($user->get('id'), $message->get('id'))) -
{{ __('app.new') }}
+ @if (!$message->get('system')) +
+
+
{{ UserModel::getNameById($message->get('userId')) }}
+ @if (ChatViewModel::handleNewMessage($user->get('id'), $message->get('id'))) +
{{ __('app.new') }}
+ @endif +
+ +
+
{{ $message->get('message') }}
+
+ +
+ {{ (new Carbon($message->get('created_at')))->diffForHumans() }} +
+
+ @else + get('id'), $message->get('id')); ?> + +
+
+
{{ UserModel::getNameById($message->get('userId')) . ' @ ' . date('Y-m-d H:s', strtotime($message->get('created_at'))) }}
+ +
{!! $message->get('message') !!}
+
+ + @if ($isNewMessage) +
+
{{ __('app.new') }}
+
@endif
- -
-
{{ $message->get('message') }}
-
- -
- {{ (new Carbon($message->get('created_at')))->diffForHumans() }} -
-
+ @endif @endforeach @endif
diff --git a/public/install/index.php b/public/install/index.php index fc2473d..e97ed78 100644 --- a/public/install/index.php +++ b/public/install/index.php @@ -370,7 +370,7 @@ $env .= 'DB_PORT=' . $dbport . PHP_EOL; $env .= 'DB_DATABASE="' . $dbdatabase . '"' . PHP_EOL; $env .= 'DB_DRIVER=mysql' . PHP_EOL; - $env .= 'DB_CHARSET="utf8"' . PHP_EOL; + $env .= 'DB_CHARSET="utf8mb4"' . PHP_EOL; $env .= '' . PHP_EOL; $env .= '# SMTP settings' . PHP_EOL; $env .= 'SMTP_FROMNAME="' . $smtpaddr . '"' . PHP_EOL; diff --git a/public/js/app.js b/public/js/app.js index de42550..46ef939 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -16,7 +16,7 @@ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _sass_app_scss__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./../sass/app.scss */ \"./app/resources/sass/app.scss\");\n/* harmony import */ var _sass_app_scss__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_sass_app_scss__WEBPACK_IMPORTED_MODULE_0__);\n/**\r\n * app.js\r\n * \r\n * Put here your application specific JavaScript implementations\r\n */\r\n\r\n\r\n\r\nwindow.axios = __webpack_require__(/*! axios */ \"./node_modules/axios/dist/browser/axios.cjs\");\r\nwindow.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';\r\n\r\nwindow.constChatMessageQueryRefreshRate = 1000 * 15;\r\nwindow.constChatUserListRefreshRate = 1000 * 15;\r\nwindow.constChatTypingRefreshRate = 2000;\r\n\r\nwindow.vue = new Vue({\r\n el: '#app',\r\n\r\n data: {\r\n bShowAddPlant: false,\r\n bShowEditText: false,\r\n bShowEditBoolean: false,\r\n bShowEditInteger: false,\r\n bShowEditDate: false,\r\n bShowEditCombo: false,\r\n bShowEditPhoto: false,\r\n bShowEditLinkText: false,\r\n bShowUploadPhoto: false,\r\n bShowCreateTask: false,\r\n bShowEditTask: false,\r\n bShowEditPreferences: false,\r\n bShowAddInventoryItem: false,\r\n bShowEditInventoryItem: false,\r\n bShowManageGroups: false,\r\n bShowRestorePassword: false,\r\n bShowCreateNewUser: false,\r\n bShowCreateNewLocation: false,\r\n bShowRemoveLocation: false,\r\n bShowPreviewImageModal: false,\r\n bShowSharePhoto: false,\r\n clsLastImagePreviewAspect: '',\r\n comboLocation: [],\r\n comboCuttingMonth: [],\r\n comboLightLevel: [],\r\n comboHealthState: [],\r\n confirmPhotoRemoval: 'Are you sure you want to remove this photo?',\r\n confirmPlantRemoval: 'Are you sure you want to remove this plant?',\r\n confirmSetAllWatered: 'Are you sure you want to update the last watered date of all these plants?',\r\n confirmSetAllRepotted: 'Are you sure you want to update the last repotted date of all these plants?',\r\n confirmInventoryItemRemoval: 'Are you sure you want to remove this item?',\r\n confirmPlantAddHistory: 'Please confirm if you want to do this action.',\r\n confirmPlantRemoveHistory: 'Please confirm if you want to do this action.',\r\n newChatMessage: 'New',\r\n currentlyOnline: 'Currently online: ',\r\n loadingPleaseWait: 'Please wait...',\r\n copiedToClipboard: 'Content has been copied to clipboard.',\r\n chatTypingEnable: false,\r\n chatTypingTimer: null,\r\n chatTypingHide: null,\r\n chatTypingCounter: 1\r\n },\r\n\r\n methods: {\r\n ajaxRequest: function (method, url, data = {}, successfunc = function(data){}, finalfunc = function(){}, config = {})\r\n {\r\n let func = window.axios.get;\r\n if (method == 'post') {\r\n func = window.axios.post;\r\n } else if (method == 'patch') {\r\n func = window.axios.patch;\r\n } else if (method == 'delete') {\r\n func = window.axios.delete;\r\n }\r\n\r\n func(url, data, config)\r\n .then(function(response){\r\n successfunc(response.data);\r\n })\r\n .catch(function (error) {\r\n console.log(error);\r\n })\r\n .finally(function(){\r\n finalfunc();\r\n }\r\n );\r\n },\r\n\r\n initNavBar: function()\r\n {\r\n const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);\r\n\r\n if ($navbarBurgers.length > 0) {\r\n $navbarBurgers.forEach( el => {\r\n el.addEventListener('click', () => {\r\n const target = el.dataset.target;\r\n const $target = document.getElementById(target);\r\n\r\n el.classList.toggle('is-active');\r\n $target.classList.toggle('is-active');\r\n });\r\n });\r\n }\r\n },\r\n\r\n showEditText: function(plant, property, defval, anchor = '')\r\n {\r\n document.getElementById('inpEditTextPlantId').value = plant;\r\n document.getElementById('inpEditTextAttribute').value = property;\r\n document.getElementById('inpEditTextValue').value = defval;\r\n document.getElementById('inpEditTextAnchor').value = anchor;\r\n window.vue.bShowEditText = true;\r\n },\r\n\r\n showEditBoolean: function(plant, property, hint, defval)\r\n {\r\n document.getElementById('inpEditBooleanPlantId').value = plant;\r\n document.getElementById('inpEditBooleanAttribute').value = property;\r\n document.getElementById('property-hint').innerHTML = hint;\r\n document.getElementById('inpEditBooleanValue').checked = defval;\r\n window.vue.bShowEditBoolean = true;\r\n },\r\n\r\n showEditInteger: function(plant, property, defval)\r\n {\r\n document.getElementById('inpEditIntegerPlantId').value = plant;\r\n document.getElementById('inpEditIntegerAttribute').value = property;\r\n document.getElementById('inpEditIntegerValue').value = defval;\r\n window.vue.bShowEditInteger = true;\r\n },\r\n\r\n showEditDate: function(plant, property, defval)\r\n {\r\n document.getElementById('inpEditDatePlantId').value = plant;\r\n document.getElementById('inpEditDateAttribute').value = property;\r\n document.getElementById('inpEditDateValue').value = defval;\r\n window.vue.bShowEditDate = true;\r\n },\r\n\r\n showEditCombo: function(plant, property, combo, defval)\r\n {\r\n document.getElementById('inpEditComboPlantId').value = plant;\r\n document.getElementById('inpEditComboAttribute').value = property;\r\n \r\n if (typeof combo !== 'object') {\r\n console.error('Invalid combo specified');\r\n return;\r\n }\r\n\r\n let sel = document.getElementById('selEditCombo');\r\n if (sel) {\r\n for (let i = sel.options.length - 1; i >= 0; i--) {\r\n sel.remove(i);\r\n }\r\n\r\n combo.forEach(function(elem, index){\r\n let opt = document.createElement('option');\r\n opt.value = elem.ident;\r\n opt.text = elem.label;\r\n sel.add(opt);\r\n });\r\n }\r\n\r\n document.getElementById('selEditCombo').value = defval;\r\n\r\n window.vue.bShowEditCombo = true;\r\n },\r\n\r\n showEditLinkText: function(plant, text, link)\r\n {\r\n document.getElementById('inpEditLinkTextPlantId').value = plant;\r\n document.getElementById('inpEditLinkTextValue').value = text;\r\n document.getElementById('inpEditLinkTextLink').value = link;\r\n window.vue.bShowEditLinkText = true;\r\n },\r\n\r\n showEditPhoto: function(plant, property)\r\n {\r\n document.getElementById('inpEditPhotoPlantId').value = plant;\r\n document.getElementById('inpEditPhotoAttribute').value = property;\r\n window.vue.bShowEditPhoto = true;\r\n },\r\n\r\n showPhotoUpload: function(plant)\r\n {\r\n document.getElementById('inpUploadPhotoPlantId').value = plant;\r\n window.vue.bShowUploadPhoto = true;\r\n },\r\n\r\n deletePhoto: function(photo, plant, target)\r\n {\r\n if (!confirm(window.vue.confirmPhotoRemoval)) {\r\n return;\r\n }\r\n\r\n window.vue.ajaxRequest('post', window.location.origin + '/plants/details/gallery/photo/remove', { photo: photo, plant: plant }, function(response){\r\n if (response.code == 200) {\r\n let elem = document.getElementById(target);\r\n if (elem) {\r\n elem.remove();\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n markHistorical: function(plant) {\r\n if (!confirm(window.vue.confirmPlantAddHistory)) {\r\n return;\r\n }\r\n\r\n location.href = window.location.origin + '/plants/history/add?plant=' + plant;\r\n },\r\n\r\n unmarkHistorical: function(plant) {\r\n if (!confirm(window.vue.confirmPlantRemoveHistory)) {\r\n return;\r\n }\r\n\r\n location.href = window.location.origin + '/plants/history/remove?plant=' + plant;\r\n },\r\n\r\n deletePlant: function(plant, retloc)\r\n {\r\n if (!confirm(window.vue.confirmPlantRemoval)) {\r\n return;\r\n }\r\n\r\n location.href = window.location.origin + '/plants/remove?plant=' + plant + '&location=' + retloc;\r\n },\r\n\r\n toggleTaskStatus: function(id)\r\n {\r\n window.vue.ajaxRequest('post', window.location.origin + '/tasks/toggle', { task: id }, function(response){\r\n if (response.code == 200) {\r\n let elem = document.getElementById('task-item-' + id);\r\n if (elem) {\r\n elem.remove();\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n editTask: function(id)\r\n {\r\n document.getElementById('inpEditTaskId').value = id;\r\n document.getElementById('inpEditTaskTitle').value = document.getElementById('task-item-title-' + id).innerText;\r\n document.getElementById('inpEditTaskDescription').value = document.getElementById('task-item-description-' + id).innerText;\r\n document.getElementById('inpEditTaskDueDate').value = document.getElementById('task-item-due-' + id).innerText;\r\n\r\n window.vue.bShowEditTask = true;\r\n },\r\n\r\n updateLastWatered: function(id)\r\n {\r\n if (!confirm(window.vue.confirmSetAllWatered)) {\r\n return;\r\n }\r\n\r\n location.href = window.location.origin + '/plants/location/' + id + '/water';\r\n },\r\n\r\n updateLastRepotted: function(id)\r\n {\r\n if (!confirm(window.vue.confirmSetAllRepotted)) {\r\n return;\r\n }\r\n\r\n location.href = window.location.origin + '/plants/location/' + id + '/repot';\r\n },\r\n\r\n expandInventoryItem: function(id)\r\n {\r\n let elem = document.getElementById(id);\r\n if (elem) {\r\n elem.classList.toggle('expand');\r\n }\r\n },\r\n\r\n incrementInventoryItem: function(id, target)\r\n {\r\n window.vue.ajaxRequest('get', window.location.origin + '/inventory/amount/increment?id=' + id, {}, function(response) {\r\n if (response.code == 200) {\r\n let elem = document.getElementById(target);\r\n if (elem) {\r\n elem.innerHTML = response.amount;\r\n\r\n if (response.amount == 0) {\r\n elem.classList.add('is-inventory-item-empty');\r\n } else {\r\n elem.classList.remove('is-inventory-item-empty');\r\n }\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n decrementInventoryItem: function(id, target)\r\n {\r\n window.vue.ajaxRequest('get', window.location.origin + '/inventory/amount/decrement?id=' + id, {}, function(response) {\r\n if (response.code == 200) {\r\n let elem = document.getElementById(target);\r\n if (elem) {\r\n elem.innerHTML = response.amount;\r\n\r\n if (response.amount == 0) {\r\n elem.classList.add('is-inventory-item-empty');\r\n } else {\r\n elem.classList.remove('is-inventory-item-empty');\r\n }\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n editInventoryItem: function(id, name, group, description)\r\n {\r\n document.getElementById('inpInventoryItemId').value = id;\r\n document.getElementById('inpInventoryItemName').value = name;\r\n document.getElementById('inpInventoryItemGroup').value = group;\r\n document.getElementById('inpInventoryItemDescription').value = document.getElementById(description).innerText;\r\n\r\n window.vue.bShowEditInventoryItem = true;\r\n },\r\n\r\n deleteInventoryItem: function(id, target)\r\n {\r\n if (!confirm(window.vue.confirmInventoryItemRemoval)) {\r\n return;\r\n }\r\n\r\n window.vue.ajaxRequest('get', window.location.origin + '/inventory/remove?id=' + id, {}, function(response) {\r\n if (response.code == 200) {\r\n let elem = document.getElementById(target);\r\n if (elem) {\r\n elem.remove();\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n editInventoryGroupItem: function(id, what, def)\r\n {\r\n let input = prompt(what, def);\r\n\r\n if (input.length > 0) {\r\n window.vue.ajaxRequest('post', window.location.origin + '/inventory/group/edit', {\r\n id: id,\r\n what: what,\r\n value: input\r\n }, function(response) {\r\n if (response.code == 200) {\r\n if (what === 'token') {\r\n document.getElementById('inventory-group-elem-token-' + id).innerText = input;\r\n } else if (what === 'label') {\r\n document.getElementById('inventory-group-elem-label-' + id).innerText = input;\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n }\r\n },\r\n\r\n removeInventoryGroupItem: function(id, target)\r\n {\r\n if (!confirm(window.vue.confirmInventoryItemRemoval)) {\r\n return;\r\n }\r\n\r\n window.vue.ajaxRequest('get', window.location.origin + '/inventory/group/remove?id=' + id, {}, function(response) {\r\n if (response.code == 200) {\r\n let elem = document.getElementById(target);\r\n if (elem) {\r\n elem.remove();\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n refreshChat: function(auth_user)\r\n {\r\n window.vue.ajaxRequest('get', window.location.origin + '/chat/query', {}, function(response) {\r\n if (response.code == 200) {\r\n response.messages.forEach(function(elem, index) {\r\n document.getElementById('chat').innerHTML = window.vue.renderNewChatMessage(elem, auth_user) + document.getElementById('chat').innerHTML;\r\n \r\n let audio = new Audio(window.location.origin + '/snd/new_message.wav');\r\n audio.onloadeddata = function() {\r\n audio.play();\r\n };\r\n });\r\n }\r\n });\r\n\r\n setTimeout(window.vue.refreshChat, window.constChatMessageQueryRefreshRate);\r\n },\r\n\r\n renderNewChatMessage: function(elem, auth_user)\r\n {\r\n let chatmsgright = '';\r\n if (elem.userId == auth_user) {\r\n chatmsgright = 'chat-message-right';\r\n }\r\n\r\n let html = `\r\n
\r\n
\r\n
` + elem.userName + `
\r\n
` + window.vue.newChatMessage + `
\r\n
\r\n\r\n
\r\n
` + elem.message + `
\r\n
\r\n\r\n
\r\n ` + elem.diffForHumans + `\r\n
\r\n
\r\n `;\r\n\r\n return html;\r\n },\r\n\r\n refreshUserList: function()\r\n {\r\n window.vue.ajaxRequest('get', window.location.origin + '/chat/user/online', {}, function(response) {\r\n if (response.code == 200) {\r\n let target = document.getElementById('chat-user-list');\r\n target.innerHTML = window.vue.currentlyOnline;\r\n\r\n response.users.forEach(function(elem, index) {\r\n let comma = '';\r\n if (index < response.users.length - 1) {\r\n comma = ', ';\r\n }\r\n \r\n target.innerHTML += elem.name + comma;\r\n });\r\n }\r\n });\r\n\r\n setTimeout(window.vue.refreshUserList, window.constChatUserListRefreshRate);\r\n },\r\n\r\n refreshTypingStatus: function()\r\n {\r\n if (!window.vue.chatTypingEnable) {\r\n return;\r\n }\r\n\r\n window.vue.ajaxRequest('get', window.location.origin + '/chat/typing/update', {}, function(response){\r\n if (response.code != 200) {\r\n console.error(response.msg);\r\n }\r\n });\r\n\r\n setTimeout(function(){\r\n window.vue.chatTypingTimer = null;\r\n }, 5000);\r\n },\r\n\r\n handleChatInput: function()\r\n {\r\n if (!window.vue.chatTypingTimer) {\r\n window.vue.chatTypingTimer = setTimeout(function(){\r\n window.vue.refreshTypingStatus();\r\n }, 1000);\r\n }\r\n },\r\n\r\n handleTypingIndicator: function()\r\n {\r\n window.vue.ajaxRequest('get', window.location.origin + '/chat/typing', {}, function(response){\r\n if (response.code == 200) {\r\n if (response.status) {\r\n let elem = document.getElementsByClassName('chat-typing-indicator')[0];\r\n elem.style.display = 'block';\r\n\r\n window.vue.chatTypingHide = setTimeout(window.vue.hideChatTypingIndicator, 6550);\r\n }\r\n }\r\n });\r\n\r\n setTimeout(window.vue.handleTypingIndicator, window.constChatTypingRefreshRate);\r\n },\r\n\r\n hideChatTypingIndicator: function()\r\n {\r\n if (window.vue.chatTypingHide !== null) {\r\n let elem = document.getElementsByClassName('chat-typing-indicator')[0];\r\n elem.style.display = 'none';\r\n\r\n window.vue.chatTypingHide = null;\r\n }\r\n },\r\n\r\n animateChatTypingIndicator: function()\r\n {\r\n let indicator = document.getElementsByClassName('chat-typing-indicator')[0];\r\n if (indicator.style.display === 'block') {\r\n window.vue.removePreviousChatIndicatorCircleStyle();\r\n\r\n let elem = document.getElementById('chat-typing-circle-' + window.vue.chatTypingCounter.toString());\r\n elem.style.color = 'rgb(50, 50, 50)';\r\n elem.classList.add('fa-lg');\r\n\r\n window.vue.chatTypingCounter++;\r\n if (window.vue.chatTypingCounter > 3) {\r\n window.vue.chatTypingCounter = 1;\r\n }\r\n }\r\n\r\n setTimeout(window.vue.animateChatTypingIndicator, 350);\r\n },\r\n\r\n removePreviousChatIndicatorCircleStyle: function()\r\n {\r\n let previous = window.vue.chatTypingCounter - 1;\r\n if (previous == 0) {\r\n previous = 3;\r\n }\r\n\r\n let elem = document.getElementById('chat-typing-circle-' + previous.toString());\r\n if (elem.classList.contains('fa-lg')) {\r\n elem.classList.remove('fa-lg');\r\n elem.style.color = 'inherit';\r\n }\r\n },\r\n\r\n textFilterElements: function(token) {\r\n let elems = document.getElementsByClassName('plant-card-title');\r\n for (let i = 0; i < elems.length; i++) {\r\n let target = elems[i].parentNode;\r\n \r\n while (!target.classList.contains('plant-card')) {\r\n target = target.parentNode;\r\n }\r\n\r\n if (!elems[i].innerText.toLowerCase().includes(token.toLowerCase())) {\r\n target.classList.add('is-hidden');\r\n } else {\r\n target.classList.remove('is-hidden');\r\n }\r\n }\r\n },\r\n\r\n filterTasks: function(token) {\r\n let elems = document.getElementsByClassName('task');\r\n for (let i = 0; i < elems.length; i++) {\r\n let elemTitle = elems[i].children[1].children[0];\r\n let elemDescription = elems[i].children[2].children[0];\r\n\r\n if ((elemTitle.innerText.toLowerCase().includes(token.toLowerCase())) || (elemDescription.innerText.toLowerCase().includes(token.toLowerCase()))) {\r\n elems[i].classList.remove('is-hidden'); \r\n } else {\r\n elems[i].classList.add('is-hidden'); \r\n }\r\n }\r\n },\r\n\r\n filterInventory: function(token) {\r\n let elems = document.getElementsByClassName('inventory-item');\r\n for (let i = 0; i < elems.length; i++) {\r\n let elemName = elems[i].children[1].children[0];\r\n let elemDescription = elems[i].children[2].children[0];\r\n\r\n if ((elemName.innerText.toLowerCase().includes(token.toLowerCase())) || (elemDescription.innerText.toLowerCase().includes(token.toLowerCase()))) {\r\n elems[i].classList.remove('is-hidden'); \r\n } else {\r\n elems[i].classList.add('is-hidden'); \r\n }\r\n }\r\n },\r\n\r\n toggleDropdown: function(elem) {\r\n if (elem.classList.contains('is-active')) {\r\n elem.classList.remove('is-active');\r\n } else {\r\n elem.classList.add('is-active');\r\n }\r\n },\r\n\r\n selectAdminTab: function(tab) {\r\n const tabs = ['environment', 'media', 'users', 'locations', 'mail', 'backup', 'info'];\r\n\r\n let selEl = document.querySelector('.admin-' + tab);\r\n if (selEl) {\r\n tabs.forEach(function(elem, index) {\r\n let otherEl = document.querySelector('.admin-' + elem);\r\n if (otherEl) {\r\n otherEl.classList.add('is-hidden');\r\n }\r\n\r\n let otherTabs = document.querySelector('.admin-tab-' + elem);\r\n if (otherTabs) {\r\n otherTabs.classList.remove('is-active');\r\n }\r\n });\r\n\r\n selEl.classList.remove('is-hidden');\r\n\r\n let selTab = document.querySelector('.admin-tab-' + tab);\r\n if (selTab) {\r\n selTab.classList.add('is-active');\r\n }\r\n }\r\n },\r\n\r\n showImagePreview: function(asset, aspect = 'is-3by5') {\r\n let img = document.getElementById('preview-image-modal-img');\r\n if (img) {\r\n img.src = asset;\r\n\r\n if (window.vue.clsLastImagePreviewAspect.length > 0) {\r\n img.parentNode.classList.remove(window.vue.clsLastImagePreviewAspect);\r\n }\r\n\r\n window.vue.clsLastImagePreviewAspect = aspect;\r\n img.parentNode.classList.add(window.vue.clsLastImagePreviewAspect);\r\n\r\n window.vue.bShowPreviewImageModal = true;\r\n }\r\n },\r\n\r\n showSharePhoto: function(asset, title, type) {\r\n document.getElementById('share-photo-title').value = title;\r\n document.getElementById('share-photo-id').value = asset;\r\n document.getElementById('share-photo-type').value = type;\r\n\r\n document.getElementById('share-photo-result').classList.add('is-hidden');\r\n document.getElementById('share-photo-error').classList.add('is-hidden');\r\n document.getElementById('share-photo-submit-action').classList.remove('is-hidden');\r\n\r\n window.vue.bShowSharePhoto = true;\r\n },\r\n\r\n performPhotoShare: function(asset, title, type, result, button, error) {\r\n let origButtonHtml = button.innerHTML;\r\n button.innerHTML = ' ' + window.vue.loadingPleaseWait;\r\n\r\n window.vue.ajaxRequest('post', window.location.origin + '/api/photo/share', { asset: asset, title: title, type: type }, function(response) {\r\n button.innerHTML = origButtonHtml;\r\n\r\n if (response.code == 200) {\r\n result.value = response.data.url;\r\n result.parentNode.parentNode.classList.remove('is-hidden');\r\n button.classList.add('is-hidden');\r\n error.classList.add('is-hidden');\r\n } else {\r\n error.innerHTML = response.msg;\r\n error.classList.remove('is-hidden');\r\n }\r\n });\r\n },\r\n\r\n generateNewToken: function(target, button) {\r\n let oldTxt = button.innerHTML;\r\n button.innerHTML = '';\r\n\r\n window.vue.ajaxRequest('post', window.location.origin + '/admin/cronjob/token', {}, function(response) {\r\n button.innerHTML = oldTxt;\r\n\r\n if (response.code == 200) {\r\n target.value = response.token;\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n startBackup: function(button, plants, gallery, tasks, inventory) {\r\n let oldText = button.innerHTML;\r\n button.innerHTML = ' ' + oldText;\r\n\r\n window.vue.ajaxRequest('post', window.location.origin + '/export/start', {\r\n plants: plants,\r\n gallery: gallery,\r\n tasks: tasks,\r\n inventory: inventory\r\n }, function(response) {\r\n button.innerHTML = oldText;\r\n\r\n if (response.code == 200) {\r\n let export_result = document.getElementById('export-result');\r\n if (export_result) {\r\n export_result.classList.remove('is-hidden');\r\n\r\n export_result.children[1].href = response.file;\r\n export_result.children[1].innerHTML = response.file;\r\n }\r\n }\r\n });\r\n },\r\n\r\n startImport: function(button, file, locations, plants, gallery, tasks, inventory) {\r\n let oldText = button.innerHTML;\r\n button.innerHTML = ' ' + oldText;\r\n \r\n let formData = new FormData();\r\n formData.append('import', file.files[0]);\r\n formData.append('locations', ((locations) ? 1 : 0));\r\n formData.append('plants', ((plants) ? 1 : 0));\r\n formData.append('gallery', ((gallery) ? 1 : 0));\r\n formData.append('tasks', ((tasks) ? 1 : 0));\r\n formData.append('inventory', ((inventory) ? 1 : 0));\r\n\r\n window.vue.ajaxRequest('post', window.location.origin + '/import/start', formData, function(response) {\r\n button.innerHTML = oldText;\r\n\r\n if (response.code == 200) {\r\n let import_result = document.getElementById('import-result');\r\n if (import_result) {\r\n import_result.classList.remove('is-hidden');\r\n }\r\n }\r\n });\r\n },\r\n\r\n copyToClipboard: function(text) {\r\n const el = document.createElement('textarea');\r\n el.value = text;\r\n document.body.appendChild(el);\r\n el.select();\r\n document.execCommand('copy');\r\n document.body.removeChild(el);\r\n alert(window.vue.copiedToClipboard);\r\n },\r\n }\r\n});\n\n//# sourceURL=webpack://asatruphp/./app/resources/js/app.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _sass_app_scss__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./../sass/app.scss */ \"./app/resources/sass/app.scss\");\n/* harmony import */ var _sass_app_scss__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_sass_app_scss__WEBPACK_IMPORTED_MODULE_0__);\n/**\r\n * app.js\r\n * \r\n * Put here your application specific JavaScript implementations\r\n */\r\n\r\n\r\n\r\nwindow.axios = __webpack_require__(/*! axios */ \"./node_modules/axios/dist/browser/axios.cjs\");\r\nwindow.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';\r\n\r\nwindow.constChatMessageQueryRefreshRate = 1000 * 15;\r\nwindow.constChatUserListRefreshRate = 1000 * 15;\r\nwindow.constChatTypingRefreshRate = 2000;\r\n\r\nwindow.vue = new Vue({\r\n el: '#app',\r\n\r\n data: {\r\n bShowAddPlant: false,\r\n bShowEditText: false,\r\n bShowEditBoolean: false,\r\n bShowEditInteger: false,\r\n bShowEditDate: false,\r\n bShowEditCombo: false,\r\n bShowEditPhoto: false,\r\n bShowEditLinkText: false,\r\n bShowUploadPhoto: false,\r\n bShowCreateTask: false,\r\n bShowEditTask: false,\r\n bShowEditPreferences: false,\r\n bShowAddInventoryItem: false,\r\n bShowEditInventoryItem: false,\r\n bShowManageGroups: false,\r\n bShowRestorePassword: false,\r\n bShowCreateNewUser: false,\r\n bShowCreateNewLocation: false,\r\n bShowRemoveLocation: false,\r\n bShowPreviewImageModal: false,\r\n bShowSharePhoto: false,\r\n clsLastImagePreviewAspect: '',\r\n comboLocation: [],\r\n comboCuttingMonth: [],\r\n comboLightLevel: [],\r\n comboHealthState: [],\r\n confirmPhotoRemoval: 'Are you sure you want to remove this photo?',\r\n confirmPlantRemoval: 'Are you sure you want to remove this plant?',\r\n confirmSetAllWatered: 'Are you sure you want to update the last watered date of all these plants?',\r\n confirmSetAllRepotted: 'Are you sure you want to update the last repotted date of all these plants?',\r\n confirmInventoryItemRemoval: 'Are you sure you want to remove this item?',\r\n confirmPlantAddHistory: 'Please confirm if you want to do this action.',\r\n confirmPlantRemoveHistory: 'Please confirm if you want to do this action.',\r\n newChatMessage: 'New',\r\n currentlyOnline: 'Currently online: ',\r\n loadingPleaseWait: 'Please wait...',\r\n copiedToClipboard: 'Content has been copied to clipboard.',\r\n chatTypingEnable: false,\r\n chatTypingTimer: null,\r\n chatTypingHide: null,\r\n chatTypingCounter: 1\r\n },\r\n\r\n methods: {\r\n ajaxRequest: function (method, url, data = {}, successfunc = function(data){}, finalfunc = function(){}, config = {})\r\n {\r\n let func = window.axios.get;\r\n if (method == 'post') {\r\n func = window.axios.post;\r\n } else if (method == 'patch') {\r\n func = window.axios.patch;\r\n } else if (method == 'delete') {\r\n func = window.axios.delete;\r\n }\r\n\r\n func(url, data, config)\r\n .then(function(response){\r\n successfunc(response.data);\r\n })\r\n .catch(function (error) {\r\n console.log(error);\r\n })\r\n .finally(function(){\r\n finalfunc();\r\n }\r\n );\r\n },\r\n\r\n initNavBar: function()\r\n {\r\n const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);\r\n\r\n if ($navbarBurgers.length > 0) {\r\n $navbarBurgers.forEach( el => {\r\n el.addEventListener('click', () => {\r\n const target = el.dataset.target;\r\n const $target = document.getElementById(target);\r\n\r\n el.classList.toggle('is-active');\r\n $target.classList.toggle('is-active');\r\n });\r\n });\r\n }\r\n },\r\n\r\n showEditText: function(plant, property, defval, anchor = '')\r\n {\r\n document.getElementById('inpEditTextPlantId').value = plant;\r\n document.getElementById('inpEditTextAttribute').value = property;\r\n document.getElementById('inpEditTextValue').value = defval;\r\n document.getElementById('inpEditTextAnchor').value = anchor;\r\n window.vue.bShowEditText = true;\r\n },\r\n\r\n showEditBoolean: function(plant, property, hint, defval)\r\n {\r\n document.getElementById('inpEditBooleanPlantId').value = plant;\r\n document.getElementById('inpEditBooleanAttribute').value = property;\r\n document.getElementById('property-hint').innerHTML = hint;\r\n document.getElementById('inpEditBooleanValue').checked = defval;\r\n window.vue.bShowEditBoolean = true;\r\n },\r\n\r\n showEditInteger: function(plant, property, defval)\r\n {\r\n document.getElementById('inpEditIntegerPlantId').value = plant;\r\n document.getElementById('inpEditIntegerAttribute').value = property;\r\n document.getElementById('inpEditIntegerValue').value = defval;\r\n window.vue.bShowEditInteger = true;\r\n },\r\n\r\n showEditDate: function(plant, property, defval)\r\n {\r\n document.getElementById('inpEditDatePlantId').value = plant;\r\n document.getElementById('inpEditDateAttribute').value = property;\r\n document.getElementById('inpEditDateValue').value = defval;\r\n window.vue.bShowEditDate = true;\r\n },\r\n\r\n showEditCombo: function(plant, property, combo, defval)\r\n {\r\n document.getElementById('inpEditComboPlantId').value = plant;\r\n document.getElementById('inpEditComboAttribute').value = property;\r\n \r\n if (typeof combo !== 'object') {\r\n console.error('Invalid combo specified');\r\n return;\r\n }\r\n\r\n let sel = document.getElementById('selEditCombo');\r\n if (sel) {\r\n for (let i = sel.options.length - 1; i >= 0; i--) {\r\n sel.remove(i);\r\n }\r\n\r\n combo.forEach(function(elem, index){\r\n let opt = document.createElement('option');\r\n opt.value = elem.ident;\r\n opt.text = elem.label;\r\n sel.add(opt);\r\n });\r\n }\r\n\r\n document.getElementById('selEditCombo').value = defval;\r\n\r\n window.vue.bShowEditCombo = true;\r\n },\r\n\r\n showEditLinkText: function(plant, text, link)\r\n {\r\n document.getElementById('inpEditLinkTextPlantId').value = plant;\r\n document.getElementById('inpEditLinkTextValue').value = text;\r\n document.getElementById('inpEditLinkTextLink').value = link;\r\n window.vue.bShowEditLinkText = true;\r\n },\r\n\r\n showEditPhoto: function(plant, property)\r\n {\r\n document.getElementById('inpEditPhotoPlantId').value = plant;\r\n document.getElementById('inpEditPhotoAttribute').value = property;\r\n window.vue.bShowEditPhoto = true;\r\n },\r\n\r\n showPhotoUpload: function(plant)\r\n {\r\n document.getElementById('inpUploadPhotoPlantId').value = plant;\r\n window.vue.bShowUploadPhoto = true;\r\n },\r\n\r\n deletePhoto: function(photo, plant, target)\r\n {\r\n if (!confirm(window.vue.confirmPhotoRemoval)) {\r\n return;\r\n }\r\n\r\n window.vue.ajaxRequest('post', window.location.origin + '/plants/details/gallery/photo/remove', { photo: photo, plant: plant }, function(response){\r\n if (response.code == 200) {\r\n let elem = document.getElementById(target);\r\n if (elem) {\r\n elem.remove();\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n markHistorical: function(plant) {\r\n if (!confirm(window.vue.confirmPlantAddHistory)) {\r\n return;\r\n }\r\n\r\n location.href = window.location.origin + '/plants/history/add?plant=' + plant;\r\n },\r\n\r\n unmarkHistorical: function(plant) {\r\n if (!confirm(window.vue.confirmPlantRemoveHistory)) {\r\n return;\r\n }\r\n\r\n location.href = window.location.origin + '/plants/history/remove?plant=' + plant;\r\n },\r\n\r\n deletePlant: function(plant, retloc)\r\n {\r\n if (!confirm(window.vue.confirmPlantRemoval)) {\r\n return;\r\n }\r\n\r\n location.href = window.location.origin + '/plants/remove?plant=' + plant + '&location=' + retloc;\r\n },\r\n\r\n toggleTaskStatus: function(id)\r\n {\r\n window.vue.ajaxRequest('post', window.location.origin + '/tasks/toggle', { task: id }, function(response){\r\n if (response.code == 200) {\r\n let elem = document.getElementById('task-item-' + id);\r\n if (elem) {\r\n elem.remove();\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n editTask: function(id)\r\n {\r\n document.getElementById('inpEditTaskId').value = id;\r\n document.getElementById('inpEditTaskTitle').value = document.getElementById('task-item-title-' + id).innerText;\r\n document.getElementById('inpEditTaskDescription').value = document.getElementById('task-item-description-' + id).innerText;\r\n document.getElementById('inpEditTaskDueDate').value = document.getElementById('task-item-due-' + id).innerText;\r\n\r\n window.vue.bShowEditTask = true;\r\n },\r\n\r\n updateLastWatered: function(id)\r\n {\r\n if (!confirm(window.vue.confirmSetAllWatered)) {\r\n return;\r\n }\r\n\r\n location.href = window.location.origin + '/plants/location/' + id + '/water';\r\n },\r\n\r\n updateLastRepotted: function(id)\r\n {\r\n if (!confirm(window.vue.confirmSetAllRepotted)) {\r\n return;\r\n }\r\n\r\n location.href = window.location.origin + '/plants/location/' + id + '/repot';\r\n },\r\n\r\n expandInventoryItem: function(id)\r\n {\r\n let elem = document.getElementById(id);\r\n if (elem) {\r\n elem.classList.toggle('expand');\r\n }\r\n },\r\n\r\n incrementInventoryItem: function(id, target)\r\n {\r\n window.vue.ajaxRequest('get', window.location.origin + '/inventory/amount/increment?id=' + id, {}, function(response) {\r\n if (response.code == 200) {\r\n let elem = document.getElementById(target);\r\n if (elem) {\r\n elem.innerHTML = response.amount;\r\n\r\n if (response.amount == 0) {\r\n elem.classList.add('is-inventory-item-empty');\r\n } else {\r\n elem.classList.remove('is-inventory-item-empty');\r\n }\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n decrementInventoryItem: function(id, target)\r\n {\r\n window.vue.ajaxRequest('get', window.location.origin + '/inventory/amount/decrement?id=' + id, {}, function(response) {\r\n if (response.code == 200) {\r\n let elem = document.getElementById(target);\r\n if (elem) {\r\n elem.innerHTML = response.amount;\r\n\r\n if (response.amount == 0) {\r\n elem.classList.add('is-inventory-item-empty');\r\n } else {\r\n elem.classList.remove('is-inventory-item-empty');\r\n }\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n editInventoryItem: function(id, name, group, description)\r\n {\r\n document.getElementById('inpInventoryItemId').value = id;\r\n document.getElementById('inpInventoryItemName').value = name;\r\n document.getElementById('inpInventoryItemGroup').value = group;\r\n document.getElementById('inpInventoryItemDescription').value = document.getElementById(description).innerText;\r\n\r\n window.vue.bShowEditInventoryItem = true;\r\n },\r\n\r\n deleteInventoryItem: function(id, target)\r\n {\r\n if (!confirm(window.vue.confirmInventoryItemRemoval)) {\r\n return;\r\n }\r\n\r\n window.vue.ajaxRequest('get', window.location.origin + '/inventory/remove?id=' + id, {}, function(response) {\r\n if (response.code == 200) {\r\n let elem = document.getElementById(target);\r\n if (elem) {\r\n elem.remove();\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n editInventoryGroupItem: function(id, what, def)\r\n {\r\n let input = prompt(what, def);\r\n\r\n if (input.length > 0) {\r\n window.vue.ajaxRequest('post', window.location.origin + '/inventory/group/edit', {\r\n id: id,\r\n what: what,\r\n value: input\r\n }, function(response) {\r\n if (response.code == 200) {\r\n if (what === 'token') {\r\n document.getElementById('inventory-group-elem-token-' + id).innerText = input;\r\n } else if (what === 'label') {\r\n document.getElementById('inventory-group-elem-label-' + id).innerText = input;\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n }\r\n },\r\n\r\n removeInventoryGroupItem: function(id, target)\r\n {\r\n if (!confirm(window.vue.confirmInventoryItemRemoval)) {\r\n return;\r\n }\r\n\r\n window.vue.ajaxRequest('get', window.location.origin + '/inventory/group/remove?id=' + id, {}, function(response) {\r\n if (response.code == 200) {\r\n let elem = document.getElementById(target);\r\n if (elem) {\r\n elem.remove();\r\n }\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n refreshChat: function(auth_user)\r\n {\r\n window.vue.ajaxRequest('get', window.location.origin + '/chat/query', {}, function(response) {\r\n if (response.code == 200) {\r\n response.messages.forEach(function(elem, index) {\r\n document.getElementById('chat').innerHTML = window.vue.renderNewChatMessage(elem, auth_user) + document.getElementById('chat').innerHTML;\r\n \r\n let audio = new Audio(window.location.origin + '/snd/new_message.wav');\r\n audio.onloadeddata = function() {\r\n audio.play();\r\n };\r\n });\r\n }\r\n });\r\n\r\n setTimeout(window.vue.refreshChat, window.constChatMessageQueryRefreshRate);\r\n },\r\n\r\n renderNewChatMessage: function(elem, auth_user)\r\n {\r\n let chatmsgright = '';\r\n if (elem.userId == auth_user) {\r\n chatmsgright = 'chat-message-right';\r\n }\r\n\r\n let html = '';\r\n\r\n if (!elem.system) {\r\n html = `\r\n
\r\n
\r\n
` + elem.userName + `
\r\n
` + window.vue.newChatMessage + `
\r\n
\r\n\r\n
\r\n
` + elem.message + `
\r\n
\r\n\r\n
\r\n ` + elem.diffForHumans + `\r\n
\r\n
\r\n `;\r\n } else {\r\n html = `\r\n
\r\n
\r\n
` + elem.userName + ` @ ` + elem.created_at + `
\r\n \r\n
` + elem.message + `
\r\n
\r\n\r\n
\r\n
` + window.vue.newChatMessage + `
\r\n
\r\n
\r\n `;\r\n }\r\n\r\n return html;\r\n },\r\n\r\n refreshUserList: function()\r\n {\r\n window.vue.ajaxRequest('get', window.location.origin + '/chat/user/online', {}, function(response) {\r\n if (response.code == 200) {\r\n let target = document.getElementById('chat-user-list');\r\n target.innerHTML = window.vue.currentlyOnline;\r\n\r\n response.users.forEach(function(elem, index) {\r\n let comma = '';\r\n if (index < response.users.length - 1) {\r\n comma = ', ';\r\n }\r\n \r\n target.innerHTML += elem.name + comma;\r\n });\r\n }\r\n });\r\n\r\n setTimeout(window.vue.refreshUserList, window.constChatUserListRefreshRate);\r\n },\r\n\r\n refreshTypingStatus: function()\r\n {\r\n if (!window.vue.chatTypingEnable) {\r\n return;\r\n }\r\n\r\n window.vue.ajaxRequest('get', window.location.origin + '/chat/typing/update', {}, function(response){\r\n if (response.code != 200) {\r\n console.error(response.msg);\r\n }\r\n });\r\n\r\n setTimeout(function(){\r\n window.vue.chatTypingTimer = null;\r\n }, 5000);\r\n },\r\n\r\n handleChatInput: function()\r\n {\r\n if (!window.vue.chatTypingTimer) {\r\n window.vue.chatTypingTimer = setTimeout(function(){\r\n window.vue.refreshTypingStatus();\r\n }, 1000);\r\n }\r\n },\r\n\r\n handleTypingIndicator: function()\r\n {\r\n window.vue.ajaxRequest('get', window.location.origin + '/chat/typing', {}, function(response){\r\n if (response.code == 200) {\r\n if (response.status) {\r\n let elem = document.getElementsByClassName('chat-typing-indicator')[0];\r\n elem.style.display = 'block';\r\n\r\n window.vue.chatTypingHide = setTimeout(window.vue.hideChatTypingIndicator, 6550);\r\n }\r\n }\r\n });\r\n\r\n setTimeout(window.vue.handleTypingIndicator, window.constChatTypingRefreshRate);\r\n },\r\n\r\n hideChatTypingIndicator: function()\r\n {\r\n if (window.vue.chatTypingHide !== null) {\r\n let elem = document.getElementsByClassName('chat-typing-indicator')[0];\r\n elem.style.display = 'none';\r\n\r\n window.vue.chatTypingHide = null;\r\n }\r\n },\r\n\r\n animateChatTypingIndicator: function()\r\n {\r\n let indicator = document.getElementsByClassName('chat-typing-indicator')[0];\r\n if (indicator.style.display === 'block') {\r\n window.vue.removePreviousChatIndicatorCircleStyle();\r\n\r\n let elem = document.getElementById('chat-typing-circle-' + window.vue.chatTypingCounter.toString());\r\n elem.style.color = 'rgb(50, 50, 50)';\r\n elem.classList.add('fa-lg');\r\n\r\n window.vue.chatTypingCounter++;\r\n if (window.vue.chatTypingCounter > 3) {\r\n window.vue.chatTypingCounter = 1;\r\n }\r\n }\r\n\r\n setTimeout(window.vue.animateChatTypingIndicator, 350);\r\n },\r\n\r\n removePreviousChatIndicatorCircleStyle: function()\r\n {\r\n let previous = window.vue.chatTypingCounter - 1;\r\n if (previous == 0) {\r\n previous = 3;\r\n }\r\n\r\n let elem = document.getElementById('chat-typing-circle-' + previous.toString());\r\n if (elem.classList.contains('fa-lg')) {\r\n elem.classList.remove('fa-lg');\r\n elem.style.color = 'inherit';\r\n }\r\n },\r\n\r\n textFilterElements: function(token) {\r\n let elems = document.getElementsByClassName('plant-card-title');\r\n for (let i = 0; i < elems.length; i++) {\r\n let target = elems[i].parentNode;\r\n \r\n while (!target.classList.contains('plant-card')) {\r\n target = target.parentNode;\r\n }\r\n\r\n if (!elems[i].innerText.toLowerCase().includes(token.toLowerCase())) {\r\n target.classList.add('is-hidden');\r\n } else {\r\n target.classList.remove('is-hidden');\r\n }\r\n }\r\n },\r\n\r\n filterTasks: function(token) {\r\n let elems = document.getElementsByClassName('task');\r\n for (let i = 0; i < elems.length; i++) {\r\n let elemTitle = elems[i].children[1].children[0];\r\n let elemDescription = elems[i].children[2].children[0];\r\n\r\n if ((elemTitle.innerText.toLowerCase().includes(token.toLowerCase())) || (elemDescription.innerText.toLowerCase().includes(token.toLowerCase()))) {\r\n elems[i].classList.remove('is-hidden'); \r\n } else {\r\n elems[i].classList.add('is-hidden'); \r\n }\r\n }\r\n },\r\n\r\n filterInventory: function(token) {\r\n let elems = document.getElementsByClassName('inventory-item');\r\n for (let i = 0; i < elems.length; i++) {\r\n let elemName = elems[i].children[1].children[0];\r\n let elemDescription = elems[i].children[2].children[0];\r\n\r\n if ((elemName.innerText.toLowerCase().includes(token.toLowerCase())) || (elemDescription.innerText.toLowerCase().includes(token.toLowerCase()))) {\r\n elems[i].classList.remove('is-hidden'); \r\n } else {\r\n elems[i].classList.add('is-hidden'); \r\n }\r\n }\r\n },\r\n\r\n toggleDropdown: function(elem) {\r\n if (elem.classList.contains('is-active')) {\r\n elem.classList.remove('is-active');\r\n } else {\r\n elem.classList.add('is-active');\r\n }\r\n },\r\n\r\n selectAdminTab: function(tab) {\r\n const tabs = ['environment', 'media', 'users', 'locations', 'mail', 'backup', 'info'];\r\n\r\n let selEl = document.querySelector('.admin-' + tab);\r\n if (selEl) {\r\n tabs.forEach(function(elem, index) {\r\n let otherEl = document.querySelector('.admin-' + elem);\r\n if (otherEl) {\r\n otherEl.classList.add('is-hidden');\r\n }\r\n\r\n let otherTabs = document.querySelector('.admin-tab-' + elem);\r\n if (otherTabs) {\r\n otherTabs.classList.remove('is-active');\r\n }\r\n });\r\n\r\n selEl.classList.remove('is-hidden');\r\n\r\n let selTab = document.querySelector('.admin-tab-' + tab);\r\n if (selTab) {\r\n selTab.classList.add('is-active');\r\n }\r\n }\r\n },\r\n\r\n showImagePreview: function(asset, aspect = 'is-3by5') {\r\n let img = document.getElementById('preview-image-modal-img');\r\n if (img) {\r\n img.src = asset;\r\n\r\n if (window.vue.clsLastImagePreviewAspect.length > 0) {\r\n img.parentNode.classList.remove(window.vue.clsLastImagePreviewAspect);\r\n }\r\n\r\n window.vue.clsLastImagePreviewAspect = aspect;\r\n img.parentNode.classList.add(window.vue.clsLastImagePreviewAspect);\r\n\r\n window.vue.bShowPreviewImageModal = true;\r\n }\r\n },\r\n\r\n showSharePhoto: function(asset, title, type) {\r\n document.getElementById('share-photo-title').value = title;\r\n document.getElementById('share-photo-id').value = asset;\r\n document.getElementById('share-photo-type').value = type;\r\n\r\n document.getElementById('share-photo-result').classList.add('is-hidden');\r\n document.getElementById('share-photo-error').classList.add('is-hidden');\r\n document.getElementById('share-photo-submit-action').classList.remove('is-hidden');\r\n\r\n window.vue.bShowSharePhoto = true;\r\n },\r\n\r\n performPhotoShare: function(asset, title, type, result, button, error) {\r\n let origButtonHtml = button.innerHTML;\r\n button.innerHTML = ' ' + window.vue.loadingPleaseWait;\r\n\r\n window.vue.ajaxRequest('post', window.location.origin + '/api/photo/share', { asset: asset, title: title, type: type }, function(response) {\r\n button.innerHTML = origButtonHtml;\r\n\r\n if (response.code == 200) {\r\n result.value = response.data.url;\r\n result.parentNode.parentNode.classList.remove('is-hidden');\r\n button.classList.add('is-hidden');\r\n error.classList.add('is-hidden');\r\n } else {\r\n error.innerHTML = response.msg;\r\n error.classList.remove('is-hidden');\r\n }\r\n });\r\n },\r\n\r\n generateNewToken: function(target, button) {\r\n let oldTxt = button.innerHTML;\r\n button.innerHTML = '';\r\n\r\n window.vue.ajaxRequest('post', window.location.origin + '/admin/cronjob/token', {}, function(response) {\r\n button.innerHTML = oldTxt;\r\n\r\n if (response.code == 200) {\r\n target.value = response.token;\r\n } else {\r\n alert(response.msg);\r\n }\r\n });\r\n },\r\n\r\n startBackup: function(button, plants, gallery, tasks, inventory) {\r\n let oldText = button.innerHTML;\r\n button.innerHTML = ' ' + oldText;\r\n\r\n window.vue.ajaxRequest('post', window.location.origin + '/export/start', {\r\n plants: plants,\r\n gallery: gallery,\r\n tasks: tasks,\r\n inventory: inventory\r\n }, function(response) {\r\n button.innerHTML = oldText;\r\n\r\n if (response.code == 200) {\r\n let export_result = document.getElementById('export-result');\r\n if (export_result) {\r\n export_result.classList.remove('is-hidden');\r\n\r\n export_result.children[1].href = response.file;\r\n export_result.children[1].innerHTML = response.file;\r\n }\r\n }\r\n });\r\n },\r\n\r\n startImport: function(button, file, locations, plants, gallery, tasks, inventory) {\r\n let oldText = button.innerHTML;\r\n button.innerHTML = ' ' + oldText;\r\n \r\n let formData = new FormData();\r\n formData.append('import', file.files[0]);\r\n formData.append('locations', ((locations) ? 1 : 0));\r\n formData.append('plants', ((plants) ? 1 : 0));\r\n formData.append('gallery', ((gallery) ? 1 : 0));\r\n formData.append('tasks', ((tasks) ? 1 : 0));\r\n formData.append('inventory', ((inventory) ? 1 : 0));\r\n\r\n window.vue.ajaxRequest('post', window.location.origin + '/import/start', formData, function(response) {\r\n button.innerHTML = oldText;\r\n\r\n if (response.code == 200) {\r\n let import_result = document.getElementById('import-result');\r\n if (import_result) {\r\n import_result.classList.remove('is-hidden');\r\n }\r\n }\r\n });\r\n },\r\n\r\n copyToClipboard: function(text) {\r\n const el = document.createElement('textarea');\r\n el.value = text;\r\n document.body.appendChild(el);\r\n el.select();\r\n document.execCommand('copy');\r\n document.body.removeChild(el);\r\n alert(window.vue.copiedToClipboard);\r\n },\r\n }\r\n});\n\n//# sourceURL=webpack://asatruphp/./app/resources/js/app.js?"); /***/ }), @@ -27,7 +27,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _sas /***/ ((module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0__);\n// Imports\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0___default()(function(i){return i[1]});\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"/*\\n app.scss\\n*/\\nhtml, body {\\n width: 100%;\\n height: 100%;\\n padding: 0;\\n margin: 0;\\n background-color: rgb(10, 10, 10);\\n}\\n\\nbody {\\n overflow-x: hidden;\\n}\\n\\n.is-image-container {\\n background-repeat: no-repeat;\\n background-size: cover;\\n padding: unset;\\n}\\n\\n.column-overlay {\\n width: 100%;\\n height: 100%;\\n padding: 20px;\\n background-color: rgba(0, 0, 0, 0.5);\\n}\\n\\nh1 {\\n font-size: 2.5em;\\n color: rgb(250, 250, 250);\\n}\\n\\nh2 {\\n font-size: 2em;\\n margin-bottom: 30px;\\n color: rgb(200, 200, 200);\\n}\\n\\n.smaller-headline {\\n font-size: 1.2em;\\n margin-bottom: 15px;\\n}\\n\\n.is-default-link {\\n color: rgb(79, 134, 202);\\n}\\n\\n.is-default-link:hover {\\n color: rgb(79, 134, 202);\\n text-decoration: underline;\\n}\\n\\n.is-yellow-link {\\n color: rgb(156, 115, 67);\\n}\\n\\n.is-yellow-link:hover {\\n color: rgb(156, 115, 67);\\n text-decoration: underline;\\n}\\n\\n.is-fixed-button-link {\\n position: relative;\\n top: 5px;\\n}\\n\\n.is-default-text-color {\\n color: rgb(150, 150, 150);\\n}\\n\\n.is-color-darker {\\n color: rgb(100, 100, 100);\\n}\\n\\n.is-color-error {\\n color: rgb(154, 73, 69);\\n}\\n\\n.is-input-dark {\\n background-color: rgba(90, 90, 90, 0.5);\\n color: rgb(200, 200, 200);\\n border: 1px solid rgb(100, 100, 100);\\n}\\n\\n.is-action-button-margin {\\n margin-right: 10px;\\n margin-bottom: 10px;\\n}\\n@media screen and (max-width: 376px) {\\n .is-action-button-margin {\\n margin-right: 15px;\\n }\\n}\\n\\n.is-underlined {\\n text-decoration: underline;\\n}\\n\\n.is-stretched {\\n width: 100%;\\n}\\n\\n.is-pointer {\\n cursor: pointer;\\n}\\n\\n.is-indicator {\\n position: absolute;\\n width: 10px;\\n height: 10px;\\n top: 17px;\\n left: 20px;\\n background-color: rgb(223, 50, 50);\\n border-radius: 50%;\\n z-index: 5;\\n}\\n@media screen and (max-width: 1087px) {\\n .is-indicator {\\n top: 10px;\\n left: 22px;\\n }\\n}\\n\\n.is-indicator-tab {\\n position: relative;\\n width: 10px;\\n height: 10px;\\n top: -4px;\\n left: -3px;\\n background-color: rgb(223, 50, 50);\\n border-radius: 50%;\\n z-index: 5;\\n}\\n\\n.is-background-success-light {\\n background-color: rgb(215, 253, 200);\\n}\\n\\n.float-right {\\n float: right;\\n}\\n\\n.belongs-to-previous-field {\\n position: relative;\\n top: -5px;\\n margin-bottom: 20px !important;\\n}\\n\\n.is-next-to-elem {\\n position: relative;\\n top: 5px;\\n margin-left: 10px;\\n}\\n@media screen and (max-width: 453px) {\\n .is-next-to-elem {\\n top: -3px;\\n margin-bottom: 20px !important;\\n margin-left: unset;\\n }\\n}\\n\\n.is-margin-bottom-20 {\\n margin-bottom: 20px !important;\\n}\\n\\n.field small {\\n color: rgb(120, 120, 120);\\n}\\n\\n.form-paragraph-modal a {\\n color: rgb(5, 67, 183);\\n}\\n\\n.form-paragraph-modal a:hover {\\n color: rgb(5, 67, 183);\\n text-decoration: underline;\\n}\\n\\n.navbar-item a {\\n color: rgb(200, 200, 200);\\n}\\n\\n.navbar-item a:hover {\\n color: rgb(250, 250, 250);\\n}\\n\\na.navbar-item:hover, a.navbar-item.is-active, .navbar-link:hover, .navbar-link.is-active {\\n background-color: rgba(255, 255, 255, 0) !important;\\n color: rgb(180, 180, 180) !important;\\n}\\n\\n.navbar-item, .navbar-burger, .navbar-link {\\n color: rgb(190, 190, 190);\\n}\\n\\n.navbar-dropdown {\\n background-color: rgb(50, 50, 48);\\n padding-top: unset;\\n}\\n\\n.navbar-item.has-dropdown:hover .navbar-link, .navbar-item.has-dropdown.is-active .navbar-link {\\n background-color: rgba(0, 0, 0, 0);\\n}\\n\\n@media screen and (max-width: 1087px) {\\n .navbar-menu {\\n background-color: rgb(50, 50, 48);\\n }\\n}\\na.navbar-burger:hover {\\n color: rgb(200, 200, 200);\\n}\\n\\n@media screen and (min-width: 1088px) {\\n .navbar-start {\\n flex-grow: 1;\\n justify-content: center;\\n }\\n}\\n\\n@media screen and (min-width: 1089px) {\\n .navbar-item-only-mobile {\\n display: none;\\n }\\n}\\n\\n@media screen and (min-width: 1089px) {\\n .navbar-dropdown-minwidth {\\n display: block;\\n top: 5px;\\n min-width: 135px;\\n text-align: center;\\n }\\n}\\n\\n@media screen and (min-width: 1089px) {\\n .navbar-dropdown-minwidth:not(.is-multiple):not(.is-loading)::after {\\n top: 20px !important;\\n }\\n}\\n\\n@media screen and (max-width: 1087px) {\\n .navbar-item-brand-mobile-right {\\n position: absolute;\\n top: 10px;\\n right: 45px;\\n }\\n}\\n@media screen and (min-width: 1089px) {\\n .navbar-item-brand-mobile-right {\\n display: none;\\n }\\n}\\n\\n@media screen and (max-width: 1087px) {\\n .navbar.is-fixed-top-pwa {\\n position: fixed;\\n top: 0;\\n left: 0;\\n right: 0;\\n z-index: 30;\\n }\\n}\\n\\n.modal {\\n z-index: 105;\\n}\\n\\n@media screen and (max-width: 1087px) {\\n .app-padding-pwa {\\n padding-top: 65px;\\n padding-bottom: 87px;\\n }\\n}\\n@media screen and (max-width: 768px) {\\n .app-padding-pwa {\\n padding-top: 41px;\\n padding-bottom: 87px;\\n }\\n}\\n\\nfieldset legend {\\n margin-bottom: 5px !important;\\n}\\n\\nfieldset .field {\\n margin-bottom: unset !important;\\n}\\n\\n.notification-badge {\\n color: rgb(255, 255, 255);\\n text-decoration: none;\\n border-radius: 2px;\\n}\\n\\n.notification-badge .notify-badge {\\n padding: 1px 7px;\\n border-radius: 50%;\\n background: rgb(255, 0, 0);\\n color: rgb(255, 255, 255);\\n font-size: 0.8em;\\n}\\n@media screen and (min-width: 1089px) {\\n .notification-badge .notify-badge {\\n position: absolute;\\n right: -5px;\\n top: 4px;\\n }\\n}\\n@media screen and (max-width: 1087px) {\\n .notification-badge .notify-badge {\\n position: relative;\\n right: -4px;\\n top: -10px;\\n }\\n}\\n\\n.notify-badge .notify-badge-count {\\n position: relative;\\n top: -2px;\\n}\\n\\n.locations {\\n text-align: center;\\n}\\n\\n.locations a {\\n color: rgb(100, 100, 100);\\n}\\n\\n.locations a:hover {\\n color: rgb(100, 100, 100);\\n}\\n\\n.location {\\n position: relative;\\n display: inline-block;\\n width: 250px;\\n height: 230px;\\n margin-left: 10px;\\n margin-right: 10px;\\n margin-bottom: 23px;\\n background-color: rgba(159, 172, 132, 0.2);\\n border: 1px solid rgb(80, 80, 80);\\n}\\n@media screen and (max-width: 830px) {\\n .location {\\n width: 134px;\\n height: 108px;\\n }\\n}\\n\\n.location:hover {\\n background-color: rgba(159, 172, 132, 0.35);\\n}\\n\\n.location-title {\\n text-align: center;\\n font-size: 2em;\\n padding-bottom: 4px;\\n margin-bottom: 20px;\\n background-color: rgba(115, 143, 100, 0.9);\\n color: #c3e4a3;\\n}\\n@media screen and (max-width: 830px) {\\n .location-title {\\n font-size: 1em;\\n padding-top: 2px;\\n padding-bottom: 5px;\\n }\\n}\\n@media screen and (min-width: 831px) {\\n .location-title {\\n padding-bottom: 10px;\\n }\\n}\\n\\n.location-icon {\\n text-align: center;\\n}\\n\\n.location-icon i {\\n color: #99ac97;\\n font-size: 5em;\\n}\\n@media screen and (max-width: 830px) {\\n .location-icon i {\\n font-size: 2em;\\n }\\n}\\n@media screen and (min-width: 831px) {\\n .location-icon i {\\n margin-top: 25px;\\n }\\n}\\n\\n.upcoming-tasks-overview {\\n position: relative;\\n text-align: center;\\n margin-bottom: 63px;\\n}\\n\\n.upcoming-tasks-overview h3 {\\n padding-top: 25px;\\n font-size: 2em;\\n color: rgb(150, 150, 150);\\n}\\n\\n.upcoming-tasks-overview-items {\\n margin-top: 25px;\\n}\\n\\n.last-added-or-authored-plants {\\n margin-top: 20px;\\n margin-bottom: 40px;\\n margin-left: -20px;\\n margin-right: -20px;\\n padding-bottom: 5px;\\n background-color: rgba(150, 150, 150, 0.3);\\n text-align: center;\\n}\\n\\n.last-added-or-authored-plants h3 {\\n padding-top: 15px;\\n font-size: 2em;\\n color: rgb(150, 150, 150);\\n}\\n\\n.margin-vertical {\\n margin-top: 20px;\\n margin-bottom: 20px;\\n}\\n\\n.margin-bottom {\\n margin-bottom: 20px;\\n}\\n\\n.sorting {\\n position: relative;\\n top: 10px;\\n margin-left: 10px;\\n}\\n\\n.sorting-control {\\n position: relative;\\n display: inline-block;\\n margin-bottom: 10px;\\n}\\n\\n.sorting-control select, .sorting-control input[type=text] {\\n color: rgb(200, 200, 200);\\n background-color: rgba(50, 50, 50, 0.9);\\n border: 1px solid rgb(100, 100, 100);\\n margin-right: 5px;\\n}\\n\\n.sorting-control input[type=text] {\\n height: 27px;\\n border-radius: 290486px;\\n padding-left: 1em;\\n}\\n\\n.select:not(.is-multiple):not(.is-loading)::after {\\n border-color: rgb(50, 115, 220) !important;\\n}\\n\\n.plants {\\n margin-top: 30px;\\n}\\n@media screen and (max-width: 552px) {\\n .plants {\\n text-align: center;\\n }\\n}\\n\\n.plants-empty {\\n position: relative;\\n margin-top: 50px;\\n text-align: center;\\n}\\n\\n.plants-empty-image img {\\n width: 256px;\\n height: 256px;\\n}\\n\\n.plants-empty-text {\\n position: relative;\\n top: -20px;\\n color: rgb(150, 150, 150);\\n font-style: italic;\\n font-size: 1.4em;\\n}\\n\\n.plant-card {\\n position: relative;\\n display: inline-block;\\n width: 265px;\\n height: 398px;\\n margin-left: 10px;\\n margin-right: 10px;\\n margin-bottom: 20px;\\n background-repeat: no-repeat;\\n background-size: cover;\\n border-radius: 10px;\\n box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.3);\\n}\\n@media screen and (max-width: 552px) {\\n .plant-card {\\n width: 145px;\\n height: 257px;\\n }\\n}\\n\\n.plant-card:hover {\\n box-shadow: 0 0 20px 0 rgba(105, 165, 85, 0.95);\\n}\\n\\n.plant-card-overlay {\\n width: 100%;\\n height: 100%;\\n background: transparent;\\n border-radius: 10px;\\n}\\n\\n.plant-card-overlay:hover {\\n background-color: rgba(0, 0, 0, 0.05);\\n}\\n\\n.plant-card-title {\\n position: absolute;\\n bottom: 0;\\n z-index: 2;\\n width: 100%;\\n height: 69px;\\n padding-top: 17px;\\n background-color: rgba(0, 0, 0, 0.5);\\n color: rgb(200, 200, 200);\\n text-align: center;\\n font-size: 1.2em;\\n border-bottom-left-radius: 10px;\\n border-bottom-right-radius: 10px;\\n}\\n@media screen and (max-width: 552px) {\\n .plant-card-title {\\n padding-top: 22px;\\n font-size: 0.9em;\\n }\\n}\\n\\n.plant-card-title-with-hint {\\n padding-top: 7px;\\n}\\n\\n.plant-card-title-longtext {\\n padding-top: 5px;\\n padding-left: 5px;\\n padding-right: 5px;\\n}\\n@media screen and (max-width: 552px) {\\n .plant-card-title-longtext {\\n padding-top: 12px;\\n padding-left: 2px;\\n padding-right: 2px;\\n }\\n}\\n\\n.plant-card-title-second {\\n color: rgb(150, 150, 150);\\n font-size: 0.8em;\\n}\\n\\n.plant-card-health-state, .plant-card-options {\\n position: absolute;\\n top: 7px;\\n right: 8px;\\n z-index: 2;\\n}\\n\\n.plant-card-options {\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-card-health-state i {\\n background-color: rgba(0, 0, 0, 0.5);\\n padding: 5px;\\n border-radius: 32%;\\n}\\n\\n@media screen and (min-width: 520px) {\\n .plant-column {\\n padding: 20px;\\n }\\n}\\n@media screen and (max-width: 520px) {\\n .plant-column {\\n display: inline-block;\\n width: 100%;\\n padding-left: 15px;\\n padding-right: 15px;\\n }\\n}\\n@media screen and (max-width: 365px) {\\n .plant-column {\\n display: inline-block;\\n padding-left: unset;\\n padding-right: unset;\\n }\\n}\\n\\n.plant-column table {\\n width: 100%;\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-column table strong {\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-column thead {\\n background-color: rgba(104, 145, 194, 0.5);\\n}\\n\\n.plant-column table td {\\n border: 1px solid rgb(200, 200, 200);\\n padding: 10px;\\n}\\n\\n.plant-details-title {\\n position: relative;\\n}\\n\\n.plant-details-title h1 {\\n display: inline-block;\\n}\\n\\n.plant-details-title h2 {\\n position: relative;\\n display: inline-block;\\n top: 14px;\\n font-size: 1.5em;\\n color: rgb(100, 100, 100);\\n float: right;\\n}\\n\\n.is-color-yes {\\n color: rgb(115, 214, 103);\\n}\\n\\n.is-color-no {\\n color: rgb(212, 67, 67);\\n}\\n\\n.is-not-available {\\n color: rgb(100, 100, 100);\\n font-style: italic;\\n}\\n\\n.plant-notes {\\n position: relative;\\n width: 100%;\\n min-width: 300px;\\n min-height: 75px;\\n padding: 10px;\\n color: rgb(200, 200, 200);\\n background-color: rgba(90, 90, 90, 0.5);\\n font-size: 1em;\\n border: 1px solid rgb(100, 100, 100);\\n border-left: 3px solid rgb(163, 122, 61);\\n border-radius: 4px;\\n}\\n\\n.plant-notes-content {\\n position: relative;\\n display: inline-block;\\n width: 90%;\\n}\\n\\n.plant-notes-edit {\\n position: relative;\\n display: inline-block;\\n float: right;\\n}\\n\\n.plant-photo {\\n position: relative;\\n width: 345px;\\n height: 543px;\\n background-repeat: no-repeat;\\n background-size: cover;\\n float: right;\\n}\\n@media screen and (max-width: 390px) {\\n .plant-photo {\\n width: 100%;\\n }\\n}\\n\\n.plant-photo-overlay {\\n width: 100%;\\n height: 45px;\\n background-color: rgba(0, 0, 0, 0.8);\\n}\\n\\n.plant-photo-view {\\n position: absolute;\\n top: 10px;\\n left: 10px;\\n}\\n\\n.plant-photo-edit {\\n position: absolute;\\n top: 10px;\\n left: 40px;\\n}\\n\\n.plant-photo-share {\\n position: absolute;\\n top: 10px;\\n right: 10px;\\n}\\n\\n.plant-photo-edit i, .plant-photo-view i, .plant-photo-share i {\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-state-in-good-standing {\\n color: rgb(115, 214, 103);\\n}\\n\\n.plant-state-overwatered {\\n color: rgb(54, 105, 201);\\n}\\n\\n.plant-state-withering {\\n color: rgb(156, 115, 67);\\n}\\n\\n.plant-state-infected {\\n color: rgb(173, 86, 86);\\n}\\n\\n.plant-warning {\\n margin-top: 10px;\\n margin-bottom: 10px;\\n color: rgb(212, 50, 50);\\n}\\n@media screen and (max-width: 510px) {\\n .plant-warning {\\n margin-bottom: 30px;\\n }\\n}\\n\\n.warning-plants {\\n position: relative;\\n width: 100%;\\n margin-top: 20px;\\n margin-bottom: 45px;\\n padding: 0 15px 15px 15px;\\n border: 1px solid rgb(100, 100, 100);\\n border-radius: 4px;\\n}\\n\\n.has-warnings {\\n background-color: rgba(123, 50, 50, 0.5);\\n}\\n\\n.is-all-ok {\\n background-color: rgba(50, 123, 56, 0.5);\\n}\\n\\n.warning-plants-title {\\n margin-top: 20px;\\n margin-bottom: 10px;\\n font-size: 1.3em;\\n color: rgb(200, 200, 200);\\n}\\n\\n.warning-plants-title-no-margin-bottom {\\n margin-bottom: unset;\\n}\\n\\n.warning-plants-title-margin-top-25 {\\n margin-top: 25px;\\n}\\n\\n.warning-plants-title-centered {\\n text-align: center;\\n}\\n\\n.warning-plants-item {\\n color: rgb(150, 150, 150);\\n margin-bottom: 10px;\\n}\\n\\n.history-years {\\n position: relative;\\n margin-top: 30px;\\n margin-bottom: 40px;\\n margin-left: 10px;\\n}\\n\\n.history-year {\\n position: relative;\\n display: inline-block;\\n margin-right: 5px;\\n margin-bottom: 20px;\\n}\\n\\n.history-year a {\\n padding-top: 5px;\\n padding-bottom: 5px;\\n padding-left: 20px;\\n padding-right: 20px;\\n color: rgb(30, 30, 30);\\n background-color: rgba(200, 200, 200, 0.5);\\n border: 1px solid rgb(150, 150, 150);\\n border-radius: 20px;\\n}\\n\\n.history-year a:hover {\\n color: rgb(30, 30, 30);\\n background-color: rgba(200, 200, 200, 0.7);\\n}\\n\\n.history-year-selected a {\\n color: rgb(30, 30, 30);\\n background-color: rgba(220, 220, 220, 0.79);\\n}\\n\\n.history-year-selected a:hover {\\n color: rgb(30, 30, 30);\\n background-color: rgba(250, 250, 250, 0.79);\\n}\\n\\n.overdue-tasks {\\n position: relative;\\n width: 100%;\\n margin-top: -10px;\\n margin-bottom: 45px;\\n padding: 0 15px 15px 15px;\\n background-color: rgba(123, 50, 50, 0.5);\\n border: 1px solid rgb(100, 100, 100);\\n border-radius: 4px;\\n}\\n\\n.overdue-tasks-title {\\n margin-top: 20px;\\n margin-bottom: 10px;\\n font-size: 1.3em;\\n color: rgb(200, 200, 200);\\n}\\n\\n.overdue-tasks-item {\\n color: rgb(150, 150, 150);\\n margin-bottom: 10px;\\n}\\n\\n.log {\\n position: relative;\\n width: 100%;\\n margin-top: 23px;\\n margin-bottom: 45px;\\n padding: 0 15px 15px 15px;\\n border: 1px solid rgb(43, 43, 43);\\n background-color: rgb(0, 0, 0);\\n border-radius: 4px;\\n}\\n\\n.log-title {\\n margin-top: 10px;\\n margin-bottom: 10px;\\n font-size: 1.3em;\\n color: rgb(0, 215, 63);\\n}\\n\\n.log-content {\\n max-height: 200px;\\n overflow-y: auto;\\n}\\n\\n.log-item {\\n color: rgb(150, 150, 150);\\n margin-bottom: 10px;\\n}\\n\\n.log-item a {\\n color: rgb(150, 150, 150);\\n}\\n\\n.log-item a:hover {\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-gallery {\\n position: relative;\\n margin-top: 10px;\\n margin-bottom: 10px;\\n}\\n\\n.plant-gallery-title {\\n margin-bottom: 20px;\\n font-size: 1.5em;\\n color: rgb(150, 150, 150);\\n}\\n\\n.plant-gallery-upload {\\n margin-bottom: 20px;\\n}\\n\\n.plant-gallery-photos {\\n margin-top: 30px;\\n}\\n\\n.plant-gallery-photos strong {\\n color: rgb(100, 100, 100);\\n}\\n\\n.plant-gallery-item {\\n position: relative;\\n display: inline-block;\\n width: 315px;\\n height: auto;\\n margin-left: 10px;\\n margin-right: 10px;\\n margin-bottom: 30px;\\n background-color: rgba(50, 50, 50, 0.8);\\n border-radius: 4px;\\n}\\n\\n.plant-gallery-item-header {\\n padding: 10px;\\n}\\n\\n.plant-gallery-item-header-label {\\n display: inline-block;\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-gallery-item-header-action {\\n display: inline-block;\\n float: right;\\n}\\n\\n.plant-gallery-item-header-action i.is-action-share {\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-gallery-item-header-action i.is-action-share:hover {\\n color: rgb(220, 220, 220);\\n}\\n\\n.plant-gallery-item-header-action i.is-action-delete {\\n color: rgb(173, 86, 86);\\n}\\n\\n.plant-gallery-item-header-action i.is-action-delete:hover {\\n color: rgb(173, 90, 90);\\n}\\n\\n.plant-gallery-item-photo {\\n position: relative;\\n}\\n\\n.plant-gallery-item-photo-overlay {\\n position: absolute;\\n z-index: 2;\\n width: 100%;\\n height: 98%;\\n}\\n\\n.plant-gallery-item-photo-overlay:hover {\\n background-color: rgba(0, 0, 0, 0.5);\\n}\\n\\n.plant-gallery-item-photo-overlay .plant-gallery-item-photo-image {\\n visibility: hidden;\\n}\\n\\n.plant-gallery-item-photo-overlay:hover .plant-gallery-item-photo-image {\\n visibility: visible;\\n}\\n\\n.plant-gallery-item-footer {\\n position: relative;\\n top: -3px;\\n padding: 10px;\\n color: rgb(100, 100, 100);\\n}\\n\\n.stats {\\n position: relative;\\n margin-top: 10px;\\n margin-bottom: 25px;\\n text-align: center;\\n}\\n\\n.stats-item {\\n position: relative;\\n display: inline-block;\\n width: 194px;\\n height: 135px;\\n margin-left: 10px;\\n margin-right: 10px;\\n margin-bottom: 20px;\\n padding: 20px;\\n background-color: rgba(150, 150, 150, 0.3);\\n border: 1px solid rgb(200, 200, 200);\\n border-radius: 4px;\\n border-left: 3px solid rgb(159, 165, 45);\\n}\\n@media screen and (max-width: 512px) {\\n .stats-item {\\n width: 149px;\\n }\\n}\\n\\n.stats-item-count {\\n color: rgb(250, 250, 250);\\n font-size: 2em;\\n text-align: center;\\n}\\n\\n.stats-item-label {\\n color: rgb(200, 200, 200);\\n font-size: 1.4em;\\n text-align: center;\\n}\\n\\n.plant-tags {\\n position: relative;\\n}\\n\\n.plant-tags-content {\\n position: relative;\\n display: inline-block;\\n width: 90%;\\n}\\n\\n.plant-tags-edit {\\n position: relative;\\n display: inline-block;\\n float: right;\\n}\\n\\n.plant-tags-item {\\n position: relative;\\n display: inline-block;\\n min-width: 90px;\\n padding-left: 10px;\\n padding-right: 10px;\\n padding-top: 5px;\\n padding-bottom: 9px;\\n margin-left: 5px;\\n margin-right: 5px;\\n margin-bottom: 16px;\\n text-align: center;\\n background-color: rgba(200, 200, 200, 0.3);\\n border: 1px solid rgb(150, 150, 150);\\n border-radius: 10px;\\n}\\n\\n.plant-tags-item:hover {\\n background-color: rgba(200, 200, 200, 0.5);\\n}\\n\\n.plant-tags-item a {\\n color: rgb(190, 190, 190);\\n}\\n\\n.plant-tags-item a:hover {\\n color: rgb(230, 230, 230);\\n}\\n\\n.tasks {\\n margin-bottom: 50px;\\n}\\n\\n.task {\\n position: relative;\\n display: inline-block;\\n width: 45%;\\n height: auto;\\n margin-left: 10px;\\n margin-right: 10px;\\n margin-bottom: 29px;\\n background-color: rgba(50, 50, 50, 0.76);\\n border: 1px solid rgb(80, 80, 80);\\n border-radius: 4px;\\n}\\n@media screen and (max-width: 580px) {\\n .task {\\n width: 95%;\\n }\\n}\\n\\n.task-header {\\n position: relative;\\n width: 100%;\\n height: 50px;\\n padding: 10px;\\n border-top-left-radius: 4px;\\n border-top-right-radius: 4px;\\n background-color: rgb(25, 25, 25);\\n}\\n\\n.task-header-title {\\n position: relative;\\n display: inline-block;\\n font-size: 1.2em;\\n color: rgb(200, 200, 200);\\n}\\n\\n.task-header-action {\\n position: relative;\\n display: inline-block;\\n float: right;\\n}\\n\\n.task-header-action a {\\n color: rgb(150, 150, 150);\\n}\\n\\n.task-description {\\n position: relative;\\n height: 150px;\\n margin-bottom: 43px;\\n padding: 10px;\\n font-size: 1em;\\n color: rgb(150, 150, 150);\\n overflow-y: auto;\\n}\\n\\n.task-description pre {\\n background-color: inherit;\\n color: inherit;\\n white-space: pre-wrap;\\n word-wrap: break-word;\\n}\\n\\n.task-footer {\\n position: absolute;\\n bottom: 0;\\n padding: 10px;\\n width: 100%;\\n background-color: rgb(10, 10, 10);\\n border-bottom-left-radius: 4px;\\n border-bottom-right-radius: 4px;\\n font-size: 0.8em;\\n}\\n\\n.task-footer-date {\\n position: relative;\\n display: inline-block;\\n width: 43%;\\n}\\n\\n.task-footer-due {\\n position: relative;\\n display: inline-block;\\n}\\n\\n.is-task-overdue {\\n color: rgb(212, 50, 50);\\n}\\n\\n.task-footer-action {\\n position: relative;\\n display: inline-block;\\n float: right;\\n}\\n\\n.task-footer-action a {\\n color: rgb(150, 150, 150);\\n}\\n\\n.tasks-all-done {\\n position: relative;\\n margin-top: 30px;\\n text-align: center;\\n}\\n\\n.tasks-all-done-image img {\\n width: 256px;\\n height: 256px;\\n}\\n\\n.tasks-all-done-text {\\n color: rgb(120, 215, 105);\\n font-size: 2em;\\n}\\n\\n.inventory {\\n margin-bottom: 50px;\\n}\\n\\n.inventory-item-group {\\n position: relative;\\n width: 100%;\\n padding-left: 10px;\\n padding-right: 10px;\\n padding-top: 5px;\\n padding-bottom: 5px;\\n background-color: rgba(200, 200, 200, 0.76);\\n border: 1px solid rgb(90, 90, 90);\\n}\\n\\n.inventory-item {\\n position: relative;\\n width: 100%;\\n padding-left: 10px;\\n padding-right: 10px;\\n padding-top: 5px;\\n padding-bottom: 5px;\\n background-color: rgba(50, 50, 50, 0.76);\\n border: 1px solid rgb(90, 90, 90);\\n}\\n\\n.inventory-item-header {\\n position: relative;\\n}\\n\\n.inventory-item-name {\\n position: relative;\\n display: inline-block;\\n min-width: 50%;\\n}\\n\\n.inventory-item-name a {\\n color: rgb(150, 150, 150);\\n}\\n\\n.inventory-item-name a:hover {\\n color: rgb(150, 150, 150);\\n}\\n\\n.inventory-item-amount {\\n position: relative;\\n display: inline-block;\\n}\\n\\n.inventory-item-amount i {\\n color: rgb(150, 150, 150);\\n}\\n\\n.inventory-item-amount span {\\n color: rgb(215, 215, 215);\\n}\\n\\n.is-inventory-item-empty {\\n color: rgb(212, 50, 50) !important;\\n}\\n\\n.inventory-item-actions {\\n position: relative;\\n display: inline-block;\\n float: right;\\n}\\n\\n.inventory-item-actions i {\\n color: rgb(100, 100, 100);\\n}\\n\\n.inventory-item-body {\\n position: relative;\\n height: 0;\\n opacity: 0;\\n overflow: hidden;\\n -webkit-transition: opacity 1s ease-out;\\n -moz-transition: opacity 1s ease-out;\\n transition: opacity 1s ease-out;\\n}\\n\\n.inventory-item-body.expand {\\n height: auto;\\n opacity: 1;\\n}\\n\\n.inventory-item-description {\\n position: relative;\\n color: rgb(100, 100, 100);\\n margin-top: 10px;\\n margin-bottom: 10px;\\n}\\n\\n.inventory-item-description pre {\\n background-color: inherit;\\n color: inherit;\\n white-space: normal;\\n}\\n\\n.inventory-item-photo {\\n position: relative;\\n text-align: center;\\n}\\n\\n.inventory-item-author {\\n position: relative;\\n color: rgb(100, 100, 100);\\n margin-top: 10px;\\n}\\n\\n.inventory-groups {\\n width: 100%;\\n}\\n\\n.inventory-groups a {\\n color: rgb(50, 50, 50);\\n}\\n\\n.inventory-groups a:hover {\\n color: rgb(50, 50, 50);\\n text-decoration: underline;\\n}\\n\\n.chat-message {\\n position: relative;\\n width: 90%;\\n padding: 15px;\\n margin-bottom: 20px;\\n background-color: rgba(200, 200, 200, 0.5);\\n border-radius: 10px;\\n}\\n\\n.chat-message-right {\\n margin-left: 10%;\\n background-color: rgba(115, 143, 100, 0.9);\\n}\\n\\n.chat-message-user {\\n position: relative;\\n font-size: 1.2em;\\n margin-bottom: 10px;\\n}\\n\\n.chat-message-new {\\n position: relative;\\n display: inline-block;\\n background-color: rgb(212, 130, 67);\\n border: 1px solid rgb(92, 64, 25);\\n color: rgb(250, 250, 250);\\n border-radius: 4px;\\n padding: 5px;\\n font-size: 0.5em;\\n text-transform: uppercase;\\n float: right;\\n}\\n\\n.chat-message-content {\\n position: relative;\\n}\\n\\n.chat-message-content pre {\\n background-color: transparent;\\n color: rgb(255, 255, 255);\\n}\\n\\n.chat-message-info {\\n position: relative;\\n margin-top: 10px;\\n font-size: 0.76em;\\n color: rgb(155, 155, 155);\\n}\\n\\n.chat-typing-indicator {\\n display: none;\\n background-color: rgba(50, 50, 50, 0.5);\\n}\\n\\n.chat-typing-indicator.visible {\\n display: block;\\n}\\n\\n.chat-user-list {\\n position: relative;\\n margin-top: 10px;\\n margin-bottom: 23px;\\n color: rgb(92, 255, 0);\\n}\\n\\n.scroll-to-top {\\n position: fixed;\\n z-index: 102;\\n bottom: 12px;\\n right: 12px;\\n}\\n\\n.scroll-to-top-inner {\\n background-color: rgb(52, 70, 56);\\n border-radius: 50%;\\n padding: 12px;\\n box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\\n}\\n\\n.scroll-to-top-inner a {\\n color: rgb(200, 200, 200);\\n}\\n\\n.auth-main {\\n width: 100%;\\n height: 100%;\\n background-repeat: no-repeat;\\n background-size: cover;\\n}\\n\\n.auth-overlay {\\n width: 100%;\\n height: 100%;\\n background-color: rgba(0, 0, 0, 0.5);\\n}\\n\\n.auth-content {\\n position: absolute;\\n top: 50%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n text-align: center;\\n padding: 20px;\\n}\\n\\n.auth-header {\\n position: relative;\\n margin-bottom: 20px;\\n}\\n\\n.auth-header img {\\n position: relative;\\n width: 128px;\\n height: 128px;\\n border-radius: 50%;\\n}\\n\\n.auth-header h1 {\\n font-size: 2.5em;\\n font-family: Quicksand, Verdana, Geneva, Tahoma, sans-serif;\\n font-weight: bold;\\n color: rgb(150, 150, 150);\\n}\\n\\n.auth-info {\\n position: relative;\\n margin-bottom: 43px;\\n}\\n\\n.auth-info-error {\\n color: rgb(154, 73, 69);\\n}\\n\\n.auth-info-success {\\n color: rgb(69, 154, 83);\\n}\\n\\n.auth-form {\\n position: relative;\\n}\\n\\n.auth-form input[type=email], .auth-form input[type=password] {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.auth-form input[type=email]::placeholder, .auth-form input[type=password]::placeholder {\\n color: rgb(200, 200, 200);\\n}\\n\\n.auth-form input[type=submit] {\\n width: 100%;\\n}\\n\\n.auth-help {\\n position: relative;\\n margin-top: 20px;\\n}\\n\\n.auth-help a {\\n color: rgb(54, 105, 203);\\n}\\n\\n.auth-help a:hover {\\n color: rgb(54, 105, 203);\\n text-decoration: underline;\\n}\\n\\n.reset-main {\\n width: 100%;\\n height: 100%;\\n background-repeat: no-repeat;\\n background-size: cover;\\n}\\n\\n.reset-overlay {\\n width: 100%;\\n height: 100%;\\n background-color: rgba(0, 0, 0, 0.5);\\n}\\n\\n.reset-content {\\n position: absolute;\\n top: 50%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n text-align: center;\\n padding: 20px;\\n}\\n\\n.reset-content h1 {\\n margin-bottom: 30px;\\n line-height: 1;\\n}\\n\\n.reset-info {\\n position: relative;\\n margin-bottom: 43px;\\n}\\n\\n.reset-info-error {\\n color: rgb(154, 73, 69);\\n}\\n\\n.reset-info-success {\\n color: rgb(69, 154, 83);\\n}\\n\\n.reset-form {\\n position: relative;\\n}\\n\\n.reset-form input[type=email], .reset-form input[type=password] {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.reset-form input[type=email]::placeholder, .reset-form input[type=password]::placeholder {\\n color: rgb(200, 200, 200);\\n}\\n\\n.reset-form input[type=submit] {\\n width: 100%;\\n}\\n\\n.admin-tabs {\\n margin-top: 23px;\\n}\\n\\n.admin-tabs a {\\n color: rgb(200, 200, 200);\\n}\\n\\n.admin-tabs a:hover {\\n color: rgb(230, 230, 230);\\n border-bottom-color: rgb(111, 172, 243);\\n}\\n\\n.admin-environment {\\n position: relative;\\n}\\n\\n.admin-environment h2 {\\n margin-top: 20px;\\n margin-bottom: 10px;\\n}\\n\\n.admin-environment label, .admin-environment span {\\n color: rgb(150, 150, 150);\\n}\\n\\n.admin-environment input, .admin-environment select {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.admin-media {\\n position: relative;\\n width: 100%;\\n}\\n\\n.admin-media h2 {\\n margin-top: 20px;\\n margin-bottom: 20px;\\n}\\n\\n.admin-media label {\\n color: rgb(150, 150, 150);\\n}\\n\\n.admin-media input, .admin-backup input {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.admin-media input[type=submit] {\\n margin-top: 10px;\\n margin-bottom: 20px;\\n}\\n\\n.admin-users {\\n position: relative;\\n width: 100%;\\n}\\n\\n.admin-users h2 {\\n margin-top: 20px;\\n margin-bottom: 20px;\\n}\\n\\n.admin-users-list {\\n position: relative;\\n}\\n\\n.admin-user-account {\\n position: relative;\\n margin-bottom: 15px;\\n}\\n\\n.admin-user-account label, .admin-user-account span {\\n color: rgb(150, 150, 150);\\n}\\n\\n.admin-user-account input, .admin-user-account select {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.admin-user-account-item {\\n position: relative;\\n display: inline-block;\\n margin-left: 5px;\\n margin-right: 5px;\\n}\\n\\n.admin-user-account-item-input {\\n width: 30%;\\n}\\n\\n.admin-user-account-actions {\\n position: relative;\\n display: inline-block;\\n}\\n\\n.admin-user-account-item-centered {\\n text-align: center;\\n}\\n\\n.admin-user-account-action-item {\\n position: relative;\\n}\\n\\n.admin-users-actions {\\n position: relative;\\n margin-top: 20px;\\n}\\n\\n.admin-locations {\\n position: relative;\\n width: 100%;\\n}\\n\\n.admin-locations h2 {\\n margin-top: 20px;\\n margin-bottom: 20px;\\n}\\n\\n.admin-locations-list {\\n position: relative;\\n}\\n\\n.admin-location {\\n position: relative;\\n margin-bottom: 15px;\\n}\\n\\n.admin-location label, .admin-location span {\\n color: rgb(150, 150, 150);\\n}\\n\\n.admin-location input {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.admin-location-item {\\n position: relative;\\n display: inline-block;\\n margin-left: 5px;\\n margin-right: 5px;\\n}\\n\\n.admin-location-item-input {\\n width: 30%;\\n}\\n\\n.admin-location-actions {\\n position: relative;\\n display: inline-block;\\n}\\n\\n.admin-location-item-centered {\\n text-align: center;\\n}\\n\\n.admin-location-action-item {\\n position: relative;\\n}\\n\\n.admin-locations-actions {\\n position: relative;\\n margin-top: 20px;\\n}\\n\\n.admin-mail {\\n position: relative;\\n}\\n\\n.admin-mail h2 {\\n margin-top: 20px;\\n margin-bottom: 10px;\\n}\\n\\n.admin-mail label, .admin-mail span {\\n color: rgb(150, 150, 150);\\n}\\n\\n.admin-mail input, .admin-mail select {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.admin-backup label, .admin-backup span {\\n color: rgb(150, 150, 150);\\n}\\n\\n.admin-backup-result {\\n position: relative;\\n padding: 10px;\\n border-radius: 5px;\\n border: 1px solid rgb(255, 255, 255);\\n background-color: rgb(185, 255, 164);\\n}\\n\\n.admin-backup-result i {\\n color: rgb(50, 50, 50);\\n}\\n\\n.admin-backup-result a {\\n color: rgb(15, 150, 43);\\n}\\n\\n.admin-backup-result a:hover {\\n color: rgb(15, 150, 43);\\n text-decoration: underline;\\n}\\n\\n.admin-info {\\n position: relative;\\n}\\n\\n.admin-info-version {\\n color: rgb(200, 200, 200);\\n font-size: 1.5em;\\n}\\n\\n.admin-info-version-smaller {\\n color: rgb(150, 150, 150);\\n font-size: 0.76em;\\n}\\n\\n.version-check {\\n position: relative;\\n margin-top: 30px;\\n}\\n\\n.version-info {\\n position: relative;\\n padding: 20px;\\n margin-top: 30px;\\n color: rgb(250, 250, 250);\\n background-color: rgba(102, 202, 160, 0.76);\\n border: 1px solid rgb(150, 236, 200);\\n border-radius: 10px;\\n}\\n\\n.version-info a {\\n color: rgb(132, 255, 123);\\n font-weight: bold;\\n}\\n\\n.version-info a:hover {\\n color: rgb(132, 255, 123);\\n text-decoration: underline;\\n}\\n\\n.bottomnav {\\n position: fixed;\\n bottom: 0;\\n width: 100%;\\n height: 70px;\\n z-index: 100;\\n padding-left: 5px;\\n padding-right: 5px;\\n background-color: rgb(50, 50, 50);\\n}\\n@media screen and (min-width: 1087px) {\\n .bottomnav {\\n display: none;\\n }\\n}\\n\\n.bottomnav-items {\\n position: relative;\\n display: block;\\n top: 10px;\\n width: 100%;\\n height: 100%;\\n margin-left: auto;\\n margin-right: auto;\\n text-align: center;\\n}\\n\\n.bottomnav-item {\\n position: relative;\\n display: inline-block;\\n width: 65px;\\n height: 50px;\\n margin-top: 6px;\\n color: rgb(150, 150, 150);\\n text-align: center;\\n font-size: 0.8em;\\n}\\n\\n.bottomnav-item a {\\n color: rgb(150, 150, 150);\\n}\\n\\n.bottomnav-item a:hover {\\n color: rgb(200, 200, 200);\\n text-decoration: none;\\n}\", \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://asatruphp/./app/resources/sass/app.scss?./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0__);\n// Imports\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_0___default()(function(i){return i[1]});\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"/*\\n app.scss\\n*/\\nhtml, body {\\n width: 100%;\\n height: 100%;\\n padding: 0;\\n margin: 0;\\n background-color: rgb(10, 10, 10);\\n}\\n\\nbody {\\n overflow-x: hidden;\\n}\\n\\n.is-image-container {\\n background-repeat: no-repeat;\\n background-size: cover;\\n padding: unset;\\n}\\n\\n.column-overlay {\\n width: 100%;\\n height: 100%;\\n padding: 20px;\\n background-color: rgba(0, 0, 0, 0.5);\\n}\\n\\nh1 {\\n font-size: 2.5em;\\n color: rgb(250, 250, 250);\\n}\\n\\nh2 {\\n font-size: 2em;\\n margin-bottom: 30px;\\n color: rgb(200, 200, 200);\\n}\\n\\n.smaller-headline {\\n font-size: 1.2em;\\n margin-bottom: 15px;\\n}\\n\\n.is-default-link {\\n color: rgb(79, 134, 202);\\n}\\n\\n.is-default-link:hover {\\n color: rgb(79, 134, 202);\\n text-decoration: underline;\\n}\\n\\n.is-yellow-link {\\n color: rgb(156, 115, 67);\\n}\\n\\n.is-yellow-link:hover {\\n color: rgb(156, 115, 67);\\n text-decoration: underline;\\n}\\n\\n.is-fixed-button-link {\\n position: relative;\\n top: 5px;\\n}\\n\\n.is-default-text-color {\\n color: rgb(150, 150, 150);\\n}\\n\\n.is-color-darker {\\n color: rgb(100, 100, 100);\\n}\\n\\n.is-color-error {\\n color: rgb(154, 73, 69);\\n}\\n\\n.is-input-dark {\\n background-color: rgba(90, 90, 90, 0.5);\\n color: rgb(200, 200, 200);\\n border: 1px solid rgb(100, 100, 100);\\n}\\n\\n.is-action-button-margin {\\n margin-right: 10px;\\n margin-bottom: 10px;\\n}\\n@media screen and (max-width: 376px) {\\n .is-action-button-margin {\\n margin-right: 15px;\\n }\\n}\\n\\n.is-underlined {\\n text-decoration: underline;\\n}\\n\\n.is-stretched {\\n width: 100%;\\n}\\n\\n.is-pointer {\\n cursor: pointer;\\n}\\n\\n.is-indicator {\\n position: absolute;\\n width: 10px;\\n height: 10px;\\n top: 17px;\\n left: 20px;\\n background-color: rgb(223, 50, 50);\\n border-radius: 50%;\\n z-index: 5;\\n}\\n@media screen and (max-width: 1087px) {\\n .is-indicator {\\n top: 10px;\\n left: 22px;\\n }\\n}\\n\\n.is-indicator-tab {\\n position: relative;\\n width: 10px;\\n height: 10px;\\n top: -4px;\\n left: -3px;\\n background-color: rgb(223, 50, 50);\\n border-radius: 50%;\\n z-index: 5;\\n}\\n\\n.is-background-success-light {\\n background-color: rgb(215, 253, 200);\\n}\\n\\n.float-right {\\n float: right;\\n}\\n\\n.belongs-to-previous-field {\\n position: relative;\\n top: -5px;\\n margin-bottom: 20px !important;\\n}\\n\\n.is-next-to-elem {\\n position: relative;\\n top: 5px;\\n margin-left: 10px;\\n}\\n@media screen and (max-width: 453px) {\\n .is-next-to-elem {\\n top: -3px;\\n margin-bottom: 20px !important;\\n margin-left: unset;\\n }\\n}\\n\\n.is-margin-bottom-20 {\\n margin-bottom: 20px !important;\\n}\\n\\n.field small {\\n color: rgb(120, 120, 120);\\n}\\n\\n.form-paragraph-modal a {\\n color: rgb(5, 67, 183);\\n}\\n\\n.form-paragraph-modal a:hover {\\n color: rgb(5, 67, 183);\\n text-decoration: underline;\\n}\\n\\n.navbar-item a {\\n color: rgb(200, 200, 200);\\n}\\n\\n.navbar-item a:hover {\\n color: rgb(250, 250, 250);\\n}\\n\\na.navbar-item:hover, a.navbar-item.is-active, .navbar-link:hover, .navbar-link.is-active {\\n background-color: rgba(255, 255, 255, 0) !important;\\n color: rgb(180, 180, 180) !important;\\n}\\n\\n.navbar-item, .navbar-burger, .navbar-link {\\n color: rgb(190, 190, 190);\\n}\\n\\n.navbar-dropdown {\\n background-color: rgb(50, 50, 48);\\n padding-top: unset;\\n}\\n\\n.navbar-item.has-dropdown:hover .navbar-link, .navbar-item.has-dropdown.is-active .navbar-link {\\n background-color: rgba(0, 0, 0, 0);\\n}\\n\\n@media screen and (max-width: 1087px) {\\n .navbar-menu {\\n background-color: rgb(50, 50, 48);\\n }\\n}\\na.navbar-burger:hover {\\n color: rgb(200, 200, 200);\\n}\\n\\n@media screen and (min-width: 1088px) {\\n .navbar-start {\\n flex-grow: 1;\\n justify-content: center;\\n }\\n}\\n\\n@media screen and (min-width: 1089px) {\\n .navbar-item-only-mobile {\\n display: none;\\n }\\n}\\n\\n@media screen and (min-width: 1089px) {\\n .navbar-dropdown-minwidth {\\n display: block;\\n top: 5px;\\n min-width: 135px;\\n text-align: center;\\n }\\n}\\n\\n@media screen and (min-width: 1089px) {\\n .navbar-dropdown-minwidth:not(.is-multiple):not(.is-loading)::after {\\n top: 20px !important;\\n }\\n}\\n\\n@media screen and (max-width: 1087px) {\\n .navbar-item-brand-mobile-right {\\n position: absolute;\\n top: 10px;\\n right: 45px;\\n }\\n}\\n@media screen and (min-width: 1089px) {\\n .navbar-item-brand-mobile-right {\\n display: none;\\n }\\n}\\n\\n@media screen and (max-width: 1087px) {\\n .navbar.is-fixed-top-pwa {\\n position: fixed;\\n top: 0;\\n left: 0;\\n right: 0;\\n z-index: 30;\\n }\\n}\\n\\n.modal {\\n z-index: 105;\\n}\\n\\n@media screen and (max-width: 1087px) {\\n .app-padding-pwa {\\n padding-top: 65px;\\n padding-bottom: 87px;\\n }\\n}\\n@media screen and (max-width: 768px) {\\n .app-padding-pwa {\\n padding-top: 41px;\\n padding-bottom: 87px;\\n }\\n}\\n\\nfieldset legend {\\n margin-bottom: 5px !important;\\n}\\n\\nfieldset .field {\\n margin-bottom: unset !important;\\n}\\n\\n.notification-badge {\\n color: rgb(255, 255, 255);\\n text-decoration: none;\\n border-radius: 2px;\\n}\\n\\n.notification-badge .notify-badge {\\n padding: 1px 7px;\\n border-radius: 50%;\\n background: rgb(255, 0, 0);\\n color: rgb(255, 255, 255);\\n font-size: 0.8em;\\n}\\n@media screen and (min-width: 1089px) {\\n .notification-badge .notify-badge {\\n position: absolute;\\n right: -5px;\\n top: 4px;\\n }\\n}\\n@media screen and (max-width: 1087px) {\\n .notification-badge .notify-badge {\\n position: relative;\\n right: -4px;\\n top: -10px;\\n }\\n}\\n\\n.notify-badge .notify-badge-count {\\n position: relative;\\n top: -2px;\\n}\\n\\n.locations {\\n text-align: center;\\n}\\n\\n.locations a {\\n color: rgb(100, 100, 100);\\n}\\n\\n.locations a:hover {\\n color: rgb(100, 100, 100);\\n}\\n\\n.location {\\n position: relative;\\n display: inline-block;\\n width: 250px;\\n height: 230px;\\n margin-left: 10px;\\n margin-right: 10px;\\n margin-bottom: 23px;\\n background-color: rgba(159, 172, 132, 0.2);\\n border: 1px solid rgb(80, 80, 80);\\n}\\n@media screen and (max-width: 830px) {\\n .location {\\n width: 134px;\\n height: 108px;\\n }\\n}\\n\\n.location:hover {\\n background-color: rgba(159, 172, 132, 0.35);\\n}\\n\\n.location-title {\\n text-align: center;\\n font-size: 2em;\\n padding-bottom: 4px;\\n margin-bottom: 20px;\\n background-color: rgba(115, 143, 100, 0.9);\\n color: #c3e4a3;\\n}\\n@media screen and (max-width: 830px) {\\n .location-title {\\n font-size: 1em;\\n padding-top: 2px;\\n padding-bottom: 5px;\\n }\\n}\\n@media screen and (min-width: 831px) {\\n .location-title {\\n padding-bottom: 10px;\\n }\\n}\\n\\n.location-icon {\\n text-align: center;\\n}\\n\\n.location-icon i {\\n color: #99ac97;\\n font-size: 5em;\\n}\\n@media screen and (max-width: 830px) {\\n .location-icon i {\\n font-size: 2em;\\n }\\n}\\n@media screen and (min-width: 831px) {\\n .location-icon i {\\n margin-top: 25px;\\n }\\n}\\n\\n.upcoming-tasks-overview {\\n position: relative;\\n text-align: center;\\n margin-bottom: 63px;\\n}\\n\\n.upcoming-tasks-overview h3 {\\n padding-top: 25px;\\n font-size: 2em;\\n color: rgb(150, 150, 150);\\n}\\n\\n.upcoming-tasks-overview-items {\\n margin-top: 25px;\\n}\\n\\n.last-added-or-authored-plants {\\n margin-top: 20px;\\n margin-bottom: 40px;\\n margin-left: -20px;\\n margin-right: -20px;\\n padding-bottom: 5px;\\n background-color: rgba(150, 150, 150, 0.3);\\n text-align: center;\\n}\\n\\n.last-added-or-authored-plants h3 {\\n padding-top: 15px;\\n font-size: 2em;\\n color: rgb(150, 150, 150);\\n}\\n\\n.margin-vertical {\\n margin-top: 20px;\\n margin-bottom: 20px;\\n}\\n\\n.margin-bottom {\\n margin-bottom: 20px;\\n}\\n\\n.sorting {\\n position: relative;\\n top: 10px;\\n margin-left: 10px;\\n}\\n\\n.sorting-control {\\n position: relative;\\n display: inline-block;\\n margin-bottom: 10px;\\n}\\n\\n.sorting-control select, .sorting-control input[type=text] {\\n color: rgb(200, 200, 200);\\n background-color: rgba(50, 50, 50, 0.9);\\n border: 1px solid rgb(100, 100, 100);\\n margin-right: 5px;\\n}\\n\\n.sorting-control input[type=text] {\\n height: 27px;\\n border-radius: 290486px;\\n padding-left: 1em;\\n}\\n\\n.select:not(.is-multiple):not(.is-loading)::after {\\n border-color: rgb(50, 115, 220) !important;\\n}\\n\\n.plants {\\n margin-top: 30px;\\n}\\n@media screen and (max-width: 552px) {\\n .plants {\\n text-align: center;\\n }\\n}\\n\\n.plants-empty {\\n position: relative;\\n margin-top: 50px;\\n text-align: center;\\n}\\n\\n.plants-empty-image img {\\n width: 256px;\\n height: 256px;\\n}\\n\\n.plants-empty-text {\\n position: relative;\\n top: -20px;\\n color: rgb(150, 150, 150);\\n font-style: italic;\\n font-size: 1.4em;\\n}\\n\\n.plant-card {\\n position: relative;\\n display: inline-block;\\n width: 265px;\\n height: 398px;\\n margin-left: 10px;\\n margin-right: 10px;\\n margin-bottom: 20px;\\n background-repeat: no-repeat;\\n background-size: cover;\\n border-radius: 10px;\\n box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.3);\\n}\\n@media screen and (max-width: 552px) {\\n .plant-card {\\n width: 145px;\\n height: 257px;\\n }\\n}\\n\\n.plant-card:hover {\\n box-shadow: 0 0 20px 0 rgba(105, 165, 85, 0.95);\\n}\\n\\n.plant-card-overlay {\\n width: 100%;\\n height: 100%;\\n background: transparent;\\n border-radius: 10px;\\n}\\n\\n.plant-card-overlay:hover {\\n background-color: rgba(0, 0, 0, 0.05);\\n}\\n\\n.plant-card-title {\\n position: absolute;\\n bottom: 0;\\n z-index: 2;\\n width: 100%;\\n height: 69px;\\n padding-top: 17px;\\n background-color: rgba(0, 0, 0, 0.5);\\n color: rgb(200, 200, 200);\\n text-align: center;\\n font-size: 1.2em;\\n border-bottom-left-radius: 10px;\\n border-bottom-right-radius: 10px;\\n}\\n@media screen and (max-width: 552px) {\\n .plant-card-title {\\n padding-top: 22px;\\n font-size: 0.9em;\\n }\\n}\\n\\n.plant-card-title-with-hint {\\n padding-top: 7px;\\n}\\n\\n.plant-card-title-longtext {\\n padding-top: 5px;\\n padding-left: 5px;\\n padding-right: 5px;\\n}\\n@media screen and (max-width: 552px) {\\n .plant-card-title-longtext {\\n padding-top: 12px;\\n padding-left: 2px;\\n padding-right: 2px;\\n }\\n}\\n\\n.plant-card-title-second {\\n color: rgb(150, 150, 150);\\n font-size: 0.8em;\\n}\\n\\n.plant-card-health-state, .plant-card-options {\\n position: absolute;\\n top: 7px;\\n right: 8px;\\n z-index: 2;\\n}\\n\\n.plant-card-options {\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-card-health-state i {\\n background-color: rgba(0, 0, 0, 0.5);\\n padding: 5px;\\n border-radius: 32%;\\n}\\n\\n@media screen and (min-width: 520px) {\\n .plant-column {\\n padding: 20px;\\n }\\n}\\n@media screen and (max-width: 520px) {\\n .plant-column {\\n display: inline-block;\\n width: 100%;\\n padding-left: 15px;\\n padding-right: 15px;\\n }\\n}\\n@media screen and (max-width: 365px) {\\n .plant-column {\\n display: inline-block;\\n padding-left: unset;\\n padding-right: unset;\\n }\\n}\\n\\n.plant-column table {\\n width: 100%;\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-column table strong {\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-column thead {\\n background-color: rgba(104, 145, 194, 0.5);\\n}\\n\\n.plant-column table td {\\n border: 1px solid rgb(200, 200, 200);\\n padding: 10px;\\n}\\n\\n.plant-details-title {\\n position: relative;\\n}\\n\\n.plant-details-title h1 {\\n display: inline-block;\\n}\\n\\n.plant-details-title h2 {\\n position: relative;\\n display: inline-block;\\n top: 14px;\\n font-size: 1.5em;\\n color: rgb(100, 100, 100);\\n float: right;\\n}\\n\\n.is-color-yes {\\n color: rgb(115, 214, 103);\\n}\\n\\n.is-color-no {\\n color: rgb(212, 67, 67);\\n}\\n\\n.is-not-available {\\n color: rgb(100, 100, 100);\\n font-style: italic;\\n}\\n\\n.plant-notes {\\n position: relative;\\n width: 100%;\\n min-width: 300px;\\n min-height: 75px;\\n padding: 10px;\\n color: rgb(200, 200, 200);\\n background-color: rgba(90, 90, 90, 0.5);\\n font-size: 1em;\\n border: 1px solid rgb(100, 100, 100);\\n border-left: 3px solid rgb(163, 122, 61);\\n border-radius: 4px;\\n}\\n\\n.plant-notes-content {\\n position: relative;\\n display: inline-block;\\n width: 90%;\\n}\\n\\n.plant-notes-edit {\\n position: relative;\\n display: inline-block;\\n float: right;\\n}\\n\\n.plant-photo {\\n position: relative;\\n width: 345px;\\n height: 543px;\\n background-repeat: no-repeat;\\n background-size: cover;\\n float: right;\\n}\\n@media screen and (max-width: 390px) {\\n .plant-photo {\\n width: 100%;\\n }\\n}\\n\\n.plant-photo-overlay {\\n width: 100%;\\n height: 45px;\\n background-color: rgba(0, 0, 0, 0.8);\\n}\\n\\n.plant-photo-view {\\n position: absolute;\\n top: 10px;\\n left: 10px;\\n}\\n\\n.plant-photo-edit {\\n position: absolute;\\n top: 10px;\\n left: 40px;\\n}\\n\\n.plant-photo-share {\\n position: absolute;\\n top: 10px;\\n right: 10px;\\n}\\n\\n.plant-photo-edit i, .plant-photo-view i, .plant-photo-share i {\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-state-in-good-standing {\\n color: rgb(115, 214, 103);\\n}\\n\\n.plant-state-overwatered {\\n color: rgb(54, 105, 201);\\n}\\n\\n.plant-state-withering {\\n color: rgb(156, 115, 67);\\n}\\n\\n.plant-state-infected {\\n color: rgb(173, 86, 86);\\n}\\n\\n.plant-warning {\\n margin-top: 10px;\\n margin-bottom: 10px;\\n color: rgb(212, 50, 50);\\n}\\n@media screen and (max-width: 510px) {\\n .plant-warning {\\n margin-bottom: 30px;\\n }\\n}\\n\\n.warning-plants {\\n position: relative;\\n width: 100%;\\n margin-top: 20px;\\n margin-bottom: 45px;\\n padding: 0 15px 15px 15px;\\n border: 1px solid rgb(100, 100, 100);\\n border-radius: 4px;\\n}\\n\\n.has-warnings {\\n background-color: rgba(123, 50, 50, 0.5);\\n}\\n\\n.is-all-ok {\\n background-color: rgba(50, 123, 56, 0.5);\\n}\\n\\n.warning-plants-title {\\n margin-top: 20px;\\n margin-bottom: 10px;\\n font-size: 1.3em;\\n color: rgb(200, 200, 200);\\n}\\n\\n.warning-plants-title-no-margin-bottom {\\n margin-bottom: unset;\\n}\\n\\n.warning-plants-title-margin-top-25 {\\n margin-top: 25px;\\n}\\n\\n.warning-plants-title-centered {\\n text-align: center;\\n}\\n\\n.warning-plants-item {\\n color: rgb(150, 150, 150);\\n margin-bottom: 10px;\\n}\\n\\n.history-years {\\n position: relative;\\n margin-top: 30px;\\n margin-bottom: 40px;\\n margin-left: 10px;\\n}\\n\\n.history-year {\\n position: relative;\\n display: inline-block;\\n margin-right: 5px;\\n margin-bottom: 20px;\\n}\\n\\n.history-year a {\\n padding-top: 5px;\\n padding-bottom: 5px;\\n padding-left: 20px;\\n padding-right: 20px;\\n color: rgb(30, 30, 30);\\n background-color: rgba(200, 200, 200, 0.5);\\n border: 1px solid rgb(150, 150, 150);\\n border-radius: 20px;\\n}\\n\\n.history-year a:hover {\\n color: rgb(30, 30, 30);\\n background-color: rgba(200, 200, 200, 0.7);\\n}\\n\\n.history-year-selected a {\\n color: rgb(30, 30, 30);\\n background-color: rgba(220, 220, 220, 0.79);\\n}\\n\\n.history-year-selected a:hover {\\n color: rgb(30, 30, 30);\\n background-color: rgba(250, 250, 250, 0.79);\\n}\\n\\n.overdue-tasks {\\n position: relative;\\n width: 100%;\\n margin-top: -10px;\\n margin-bottom: 45px;\\n padding: 0 15px 15px 15px;\\n background-color: rgba(123, 50, 50, 0.5);\\n border: 1px solid rgb(100, 100, 100);\\n border-radius: 4px;\\n}\\n\\n.overdue-tasks-title {\\n margin-top: 20px;\\n margin-bottom: 10px;\\n font-size: 1.3em;\\n color: rgb(200, 200, 200);\\n}\\n\\n.overdue-tasks-item {\\n color: rgb(150, 150, 150);\\n margin-bottom: 10px;\\n}\\n\\n.log {\\n position: relative;\\n width: 100%;\\n margin-top: 23px;\\n margin-bottom: 45px;\\n padding: 0 15px 15px 15px;\\n border: 1px solid rgb(43, 43, 43);\\n background-color: rgb(0, 0, 0);\\n border-radius: 4px;\\n}\\n\\n.log-title {\\n margin-top: 10px;\\n margin-bottom: 10px;\\n font-size: 1.3em;\\n color: rgb(0, 215, 63);\\n}\\n\\n.log-content {\\n max-height: 200px;\\n overflow-y: auto;\\n}\\n\\n.log-item {\\n color: rgb(150, 150, 150);\\n margin-bottom: 10px;\\n}\\n\\n.log-item a {\\n color: rgb(150, 150, 150);\\n}\\n\\n.log-item a:hover {\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-gallery {\\n position: relative;\\n margin-top: 10px;\\n margin-bottom: 10px;\\n}\\n\\n.plant-gallery-title {\\n margin-bottom: 20px;\\n font-size: 1.5em;\\n color: rgb(150, 150, 150);\\n}\\n\\n.plant-gallery-upload {\\n margin-bottom: 20px;\\n}\\n\\n.plant-gallery-photos {\\n margin-top: 30px;\\n}\\n\\n.plant-gallery-photos strong {\\n color: rgb(100, 100, 100);\\n}\\n\\n.plant-gallery-item {\\n position: relative;\\n display: inline-block;\\n width: 315px;\\n height: auto;\\n margin-left: 10px;\\n margin-right: 10px;\\n margin-bottom: 30px;\\n background-color: rgba(50, 50, 50, 0.8);\\n border-radius: 4px;\\n}\\n\\n.plant-gallery-item-header {\\n padding: 10px;\\n}\\n\\n.plant-gallery-item-header-label {\\n display: inline-block;\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-gallery-item-header-action {\\n display: inline-block;\\n float: right;\\n}\\n\\n.plant-gallery-item-header-action i.is-action-share {\\n color: rgb(200, 200, 200);\\n}\\n\\n.plant-gallery-item-header-action i.is-action-share:hover {\\n color: rgb(220, 220, 220);\\n}\\n\\n.plant-gallery-item-header-action i.is-action-delete {\\n color: rgb(173, 86, 86);\\n}\\n\\n.plant-gallery-item-header-action i.is-action-delete:hover {\\n color: rgb(173, 90, 90);\\n}\\n\\n.plant-gallery-item-photo {\\n position: relative;\\n}\\n\\n.plant-gallery-item-photo-overlay {\\n position: absolute;\\n z-index: 2;\\n width: 100%;\\n height: 98%;\\n}\\n\\n.plant-gallery-item-photo-overlay:hover {\\n background-color: rgba(0, 0, 0, 0.5);\\n}\\n\\n.plant-gallery-item-photo-overlay .plant-gallery-item-photo-image {\\n visibility: hidden;\\n}\\n\\n.plant-gallery-item-photo-overlay:hover .plant-gallery-item-photo-image {\\n visibility: visible;\\n}\\n\\n.plant-gallery-item-footer {\\n position: relative;\\n top: -3px;\\n padding: 10px;\\n color: rgb(100, 100, 100);\\n}\\n\\n.stats {\\n position: relative;\\n margin-top: 10px;\\n margin-bottom: 25px;\\n text-align: center;\\n}\\n\\n.stats-item {\\n position: relative;\\n display: inline-block;\\n width: 194px;\\n height: 135px;\\n margin-left: 10px;\\n margin-right: 10px;\\n margin-bottom: 20px;\\n padding: 20px;\\n background-color: rgba(150, 150, 150, 0.3);\\n border: 1px solid rgb(200, 200, 200);\\n border-radius: 4px;\\n border-left: 3px solid rgb(159, 165, 45);\\n}\\n@media screen and (max-width: 512px) {\\n .stats-item {\\n width: 149px;\\n }\\n}\\n\\n.stats-item-count {\\n color: rgb(250, 250, 250);\\n font-size: 2em;\\n text-align: center;\\n}\\n\\n.stats-item-label {\\n color: rgb(200, 200, 200);\\n font-size: 1.4em;\\n text-align: center;\\n}\\n\\n.plant-tags {\\n position: relative;\\n}\\n\\n.plant-tags-content {\\n position: relative;\\n display: inline-block;\\n width: 90%;\\n}\\n\\n.plant-tags-edit {\\n position: relative;\\n display: inline-block;\\n float: right;\\n}\\n\\n.plant-tags-item {\\n position: relative;\\n display: inline-block;\\n min-width: 90px;\\n padding-left: 10px;\\n padding-right: 10px;\\n padding-top: 5px;\\n padding-bottom: 9px;\\n margin-left: 5px;\\n margin-right: 5px;\\n margin-bottom: 16px;\\n text-align: center;\\n background-color: rgba(200, 200, 200, 0.3);\\n border: 1px solid rgb(150, 150, 150);\\n border-radius: 10px;\\n}\\n\\n.plant-tags-item:hover {\\n background-color: rgba(200, 200, 200, 0.5);\\n}\\n\\n.plant-tags-item a {\\n color: rgb(190, 190, 190);\\n}\\n\\n.plant-tags-item a:hover {\\n color: rgb(230, 230, 230);\\n}\\n\\n.tasks {\\n margin-bottom: 50px;\\n}\\n\\n.task {\\n position: relative;\\n display: inline-block;\\n width: 45%;\\n height: auto;\\n margin-left: 10px;\\n margin-right: 10px;\\n margin-bottom: 29px;\\n background-color: rgba(50, 50, 50, 0.76);\\n border: 1px solid rgb(80, 80, 80);\\n border-radius: 4px;\\n}\\n@media screen and (max-width: 580px) {\\n .task {\\n width: 95%;\\n }\\n}\\n\\n.task-header {\\n position: relative;\\n width: 100%;\\n height: 50px;\\n padding: 10px;\\n border-top-left-radius: 4px;\\n border-top-right-radius: 4px;\\n background-color: rgb(25, 25, 25);\\n}\\n\\n.task-header-title {\\n position: relative;\\n display: inline-block;\\n font-size: 1.2em;\\n color: rgb(200, 200, 200);\\n}\\n\\n.task-header-action {\\n position: relative;\\n display: inline-block;\\n float: right;\\n}\\n\\n.task-header-action a {\\n color: rgb(150, 150, 150);\\n}\\n\\n.task-description {\\n position: relative;\\n height: 150px;\\n margin-bottom: 43px;\\n padding: 10px;\\n font-size: 1em;\\n color: rgb(150, 150, 150);\\n overflow-y: auto;\\n}\\n\\n.task-description pre {\\n background-color: inherit;\\n color: inherit;\\n white-space: pre-wrap;\\n word-wrap: break-word;\\n}\\n\\n.task-footer {\\n position: absolute;\\n bottom: 0;\\n padding: 10px;\\n width: 100%;\\n background-color: rgb(10, 10, 10);\\n border-bottom-left-radius: 4px;\\n border-bottom-right-radius: 4px;\\n font-size: 0.8em;\\n}\\n\\n.task-footer-date {\\n position: relative;\\n display: inline-block;\\n width: 43%;\\n}\\n\\n.task-footer-due {\\n position: relative;\\n display: inline-block;\\n}\\n\\n.is-task-overdue {\\n color: rgb(212, 50, 50);\\n}\\n\\n.task-footer-action {\\n position: relative;\\n display: inline-block;\\n float: right;\\n}\\n\\n.task-footer-action a {\\n color: rgb(150, 150, 150);\\n}\\n\\n.tasks-all-done {\\n position: relative;\\n margin-top: 30px;\\n text-align: center;\\n}\\n\\n.tasks-all-done-image img {\\n width: 256px;\\n height: 256px;\\n}\\n\\n.tasks-all-done-text {\\n color: rgb(120, 215, 105);\\n font-size: 2em;\\n}\\n\\n.inventory {\\n margin-bottom: 50px;\\n}\\n\\n.inventory-item-group {\\n position: relative;\\n width: 100%;\\n padding-left: 10px;\\n padding-right: 10px;\\n padding-top: 5px;\\n padding-bottom: 5px;\\n background-color: rgba(200, 200, 200, 0.76);\\n border: 1px solid rgb(90, 90, 90);\\n}\\n\\n.inventory-item {\\n position: relative;\\n width: 100%;\\n padding-left: 10px;\\n padding-right: 10px;\\n padding-top: 5px;\\n padding-bottom: 5px;\\n background-color: rgba(50, 50, 50, 0.76);\\n border: 1px solid rgb(90, 90, 90);\\n}\\n\\n.inventory-item-header {\\n position: relative;\\n}\\n\\n.inventory-item-name {\\n position: relative;\\n display: inline-block;\\n min-width: 50%;\\n}\\n\\n.inventory-item-name a {\\n color: rgb(150, 150, 150);\\n}\\n\\n.inventory-item-name a:hover {\\n color: rgb(150, 150, 150);\\n}\\n\\n.inventory-item-amount {\\n position: relative;\\n display: inline-block;\\n}\\n\\n.inventory-item-amount i {\\n color: rgb(150, 150, 150);\\n}\\n\\n.inventory-item-amount span {\\n color: rgb(215, 215, 215);\\n}\\n\\n.is-inventory-item-empty {\\n color: rgb(212, 50, 50) !important;\\n}\\n\\n.inventory-item-actions {\\n position: relative;\\n display: inline-block;\\n float: right;\\n}\\n\\n.inventory-item-actions i {\\n color: rgb(100, 100, 100);\\n}\\n\\n.inventory-item-body {\\n position: relative;\\n height: 0;\\n opacity: 0;\\n overflow: hidden;\\n -webkit-transition: opacity 1s ease-out;\\n -moz-transition: opacity 1s ease-out;\\n transition: opacity 1s ease-out;\\n}\\n\\n.inventory-item-body.expand {\\n height: auto;\\n opacity: 1;\\n}\\n\\n.inventory-item-description {\\n position: relative;\\n color: rgb(100, 100, 100);\\n margin-top: 10px;\\n margin-bottom: 10px;\\n}\\n\\n.inventory-item-description pre {\\n background-color: inherit;\\n color: inherit;\\n white-space: normal;\\n}\\n\\n.inventory-item-photo {\\n position: relative;\\n text-align: center;\\n}\\n\\n.inventory-item-author {\\n position: relative;\\n color: rgb(100, 100, 100);\\n margin-top: 10px;\\n}\\n\\n.inventory-groups {\\n width: 100%;\\n}\\n\\n.inventory-groups a {\\n color: rgb(50, 50, 50);\\n}\\n\\n.inventory-groups a:hover {\\n color: rgb(50, 50, 50);\\n text-decoration: underline;\\n}\\n\\n.chat-message {\\n position: relative;\\n width: 90%;\\n padding: 15px;\\n margin-bottom: 20px;\\n background-color: rgba(200, 200, 200, 0.5);\\n border-radius: 10px;\\n}\\n\\n.chat-message-right {\\n margin-left: 10%;\\n background-color: rgba(115, 143, 100, 0.9);\\n}\\n\\n.chat-message-user {\\n position: relative;\\n font-size: 1.2em;\\n margin-bottom: 10px;\\n}\\n\\n.chat-message-new {\\n position: relative;\\n display: inline-block;\\n background-color: rgb(212, 130, 67);\\n border: 1px solid rgb(92, 64, 25);\\n color: rgb(250, 250, 250);\\n border-radius: 4px;\\n padding: 5px;\\n font-size: 0.5em;\\n text-transform: uppercase;\\n float: right;\\n}\\n\\n.chat-message-content {\\n position: relative;\\n}\\n\\n.chat-message-content pre {\\n background-color: transparent;\\n color: rgb(255, 255, 255);\\n}\\n\\n.chat-message-info {\\n position: relative;\\n margin-top: 10px;\\n font-size: 0.76em;\\n color: rgb(155, 155, 155);\\n}\\n\\n.chat-typing-indicator {\\n display: none;\\n background-color: rgba(50, 50, 50, 0.5);\\n}\\n\\n.chat-typing-indicator.visible {\\n display: block;\\n}\\n\\n.chat-user-list {\\n position: relative;\\n margin-top: 10px;\\n margin-bottom: 23px;\\n color: rgb(92, 255, 0);\\n}\\n\\n.system-message {\\n position: relative;\\n background-color: rgb(205, 202, 165);\\n border-radius: 10px;\\n padding: 20px;\\n margin-bottom: 20px;\\n}\\n\\n.system-message-left {\\n position: relative;\\n display: inline-block;\\n width: 93%;\\n}\\n@media screen and (max-width: 1000px) {\\n .system-message-left {\\n width: 80%;\\n }\\n}\\n\\n.system-message-left-new {\\n top: -3px;\\n}\\n\\n.system-message-right {\\n position: relative;\\n display: inline-block;\\n top: 3px;\\n}\\n\\n.system-message-context {\\n position: relative;\\n display: inline-block;\\n font-weight: bold;\\n}\\n\\n.system-message-content {\\n position: relative;\\n display: inline-block;\\n}\\n@media screen and (max-width: 768px) {\\n .system-message-content {\\n margin-top: 10px;\\n }\\n}\\n\\n.system-message-content a {\\n color: rgb(135, 75, 5);\\n}\\n\\n.system-message-content a:hover {\\n color: rgb(135, 75, 5);\\n text-decoration: underline;\\n}\\n\\n@media screen and (max-width: 768px) {\\n .system-message-new {\\n top: -58px;\\n }\\n}\\n\\n.scroll-to-top {\\n position: fixed;\\n z-index: 102;\\n bottom: 12px;\\n right: 12px;\\n}\\n\\n.scroll-to-top-inner {\\n background-color: rgb(52, 70, 56);\\n border-radius: 50%;\\n padding: 12px;\\n box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\\n}\\n\\n.scroll-to-top-inner a {\\n color: rgb(200, 200, 200);\\n}\\n\\n.auth-main {\\n width: 100%;\\n height: 100%;\\n background-repeat: no-repeat;\\n background-size: cover;\\n}\\n\\n.auth-overlay {\\n width: 100%;\\n height: 100%;\\n background-color: rgba(0, 0, 0, 0.5);\\n}\\n\\n.auth-content {\\n position: absolute;\\n top: 50%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n text-align: center;\\n padding: 20px;\\n}\\n\\n.auth-header {\\n position: relative;\\n margin-bottom: 20px;\\n}\\n\\n.auth-header img {\\n position: relative;\\n width: 128px;\\n height: 128px;\\n border-radius: 50%;\\n}\\n\\n.auth-header h1 {\\n font-size: 2.5em;\\n font-family: Quicksand, Verdana, Geneva, Tahoma, sans-serif;\\n font-weight: bold;\\n color: rgb(150, 150, 150);\\n}\\n\\n.auth-info {\\n position: relative;\\n margin-bottom: 43px;\\n}\\n\\n.auth-info-error {\\n color: rgb(154, 73, 69);\\n}\\n\\n.auth-info-success {\\n color: rgb(69, 154, 83);\\n}\\n\\n.auth-form {\\n position: relative;\\n}\\n\\n.auth-form input[type=email], .auth-form input[type=password] {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.auth-form input[type=email]::placeholder, .auth-form input[type=password]::placeholder {\\n color: rgb(200, 200, 200);\\n}\\n\\n.auth-form input[type=submit] {\\n width: 100%;\\n}\\n\\n.auth-help {\\n position: relative;\\n margin-top: 20px;\\n}\\n\\n.auth-help a {\\n color: rgb(54, 105, 203);\\n}\\n\\n.auth-help a:hover {\\n color: rgb(54, 105, 203);\\n text-decoration: underline;\\n}\\n\\n.reset-main {\\n width: 100%;\\n height: 100%;\\n background-repeat: no-repeat;\\n background-size: cover;\\n}\\n\\n.reset-overlay {\\n width: 100%;\\n height: 100%;\\n background-color: rgba(0, 0, 0, 0.5);\\n}\\n\\n.reset-content {\\n position: absolute;\\n top: 50%;\\n left: 50%;\\n transform: translate(-50%, -50%);\\n text-align: center;\\n padding: 20px;\\n}\\n\\n.reset-content h1 {\\n margin-bottom: 30px;\\n line-height: 1;\\n}\\n\\n.reset-info {\\n position: relative;\\n margin-bottom: 43px;\\n}\\n\\n.reset-info-error {\\n color: rgb(154, 73, 69);\\n}\\n\\n.reset-info-success {\\n color: rgb(69, 154, 83);\\n}\\n\\n.reset-form {\\n position: relative;\\n}\\n\\n.reset-form input[type=email], .reset-form input[type=password] {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.reset-form input[type=email]::placeholder, .reset-form input[type=password]::placeholder {\\n color: rgb(200, 200, 200);\\n}\\n\\n.reset-form input[type=submit] {\\n width: 100%;\\n}\\n\\n.admin-tabs {\\n margin-top: 23px;\\n}\\n\\n.admin-tabs a {\\n color: rgb(200, 200, 200);\\n}\\n\\n.admin-tabs a:hover {\\n color: rgb(230, 230, 230);\\n border-bottom-color: rgb(111, 172, 243);\\n}\\n\\n.admin-environment {\\n position: relative;\\n}\\n\\n.admin-environment h2 {\\n margin-top: 20px;\\n margin-bottom: 10px;\\n}\\n\\n.admin-environment label, .admin-environment span {\\n color: rgb(150, 150, 150);\\n}\\n\\n.admin-environment input, .admin-environment select {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.admin-media {\\n position: relative;\\n width: 100%;\\n}\\n\\n.admin-media h2 {\\n margin-top: 20px;\\n margin-bottom: 20px;\\n}\\n\\n.admin-media label {\\n color: rgb(150, 150, 150);\\n}\\n\\n.admin-media input, .admin-backup input {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.admin-media input[type=submit] {\\n margin-top: 10px;\\n margin-bottom: 20px;\\n}\\n\\n.admin-users {\\n position: relative;\\n width: 100%;\\n}\\n\\n.admin-users h2 {\\n margin-top: 20px;\\n margin-bottom: 20px;\\n}\\n\\n.admin-users-list {\\n position: relative;\\n}\\n\\n.admin-user-account {\\n position: relative;\\n margin-bottom: 15px;\\n}\\n\\n.admin-user-account label, .admin-user-account span {\\n color: rgb(150, 150, 150);\\n}\\n\\n.admin-user-account input, .admin-user-account select {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.admin-user-account-item {\\n position: relative;\\n display: inline-block;\\n margin-left: 5px;\\n margin-right: 5px;\\n}\\n\\n.admin-user-account-item-input {\\n width: 30%;\\n}\\n\\n.admin-user-account-actions {\\n position: relative;\\n display: inline-block;\\n}\\n\\n.admin-user-account-item-centered {\\n text-align: center;\\n}\\n\\n.admin-user-account-action-item {\\n position: relative;\\n}\\n\\n.admin-users-actions {\\n position: relative;\\n margin-top: 20px;\\n}\\n\\n.admin-locations {\\n position: relative;\\n width: 100%;\\n}\\n\\n.admin-locations h2 {\\n margin-top: 20px;\\n margin-bottom: 20px;\\n}\\n\\n.admin-locations-list {\\n position: relative;\\n}\\n\\n.admin-location {\\n position: relative;\\n margin-bottom: 15px;\\n}\\n\\n.admin-location label, .admin-location span {\\n color: rgb(150, 150, 150);\\n}\\n\\n.admin-location input {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.admin-location-item {\\n position: relative;\\n display: inline-block;\\n margin-left: 5px;\\n margin-right: 5px;\\n}\\n\\n.admin-location-item-input {\\n width: 30%;\\n}\\n\\n.admin-location-actions {\\n position: relative;\\n display: inline-block;\\n}\\n\\n.admin-location-item-centered {\\n text-align: center;\\n}\\n\\n.admin-location-action-item {\\n position: relative;\\n}\\n\\n.admin-locations-actions {\\n position: relative;\\n margin-top: 20px;\\n}\\n\\n.admin-mail {\\n position: relative;\\n}\\n\\n.admin-mail h2 {\\n margin-top: 20px;\\n margin-bottom: 10px;\\n}\\n\\n.admin-mail label, .admin-mail span {\\n color: rgb(150, 150, 150);\\n}\\n\\n.admin-mail input, .admin-mail select {\\n color: rgb(150, 150, 150);\\n background-color: rgb(50, 50, 50);\\n}\\n\\n.admin-backup label, .admin-backup span {\\n color: rgb(150, 150, 150);\\n}\\n\\n.admin-backup-result {\\n position: relative;\\n padding: 10px;\\n border-radius: 5px;\\n border: 1px solid rgb(255, 255, 255);\\n background-color: rgb(185, 255, 164);\\n}\\n\\n.admin-backup-result i {\\n color: rgb(50, 50, 50);\\n}\\n\\n.admin-backup-result a {\\n color: rgb(15, 150, 43);\\n}\\n\\n.admin-backup-result a:hover {\\n color: rgb(15, 150, 43);\\n text-decoration: underline;\\n}\\n\\n.admin-info {\\n position: relative;\\n}\\n\\n.admin-info-version {\\n color: rgb(200, 200, 200);\\n font-size: 1.5em;\\n}\\n\\n.admin-info-version-smaller {\\n color: rgb(150, 150, 150);\\n font-size: 0.76em;\\n}\\n\\n.version-check {\\n position: relative;\\n margin-top: 30px;\\n}\\n\\n.version-info {\\n position: relative;\\n padding: 20px;\\n margin-top: 30px;\\n color: rgb(250, 250, 250);\\n background-color: rgba(102, 202, 160, 0.76);\\n border: 1px solid rgb(150, 236, 200);\\n border-radius: 10px;\\n}\\n\\n.version-info a {\\n color: rgb(132, 255, 123);\\n font-weight: bold;\\n}\\n\\n.version-info a:hover {\\n color: rgb(132, 255, 123);\\n text-decoration: underline;\\n}\\n\\n.bottomnav {\\n position: fixed;\\n bottom: 0;\\n width: 100%;\\n height: 70px;\\n z-index: 100;\\n padding-left: 5px;\\n padding-right: 5px;\\n background-color: rgb(50, 50, 50);\\n}\\n@media screen and (min-width: 1087px) {\\n .bottomnav {\\n display: none;\\n }\\n}\\n\\n.bottomnav-items {\\n position: relative;\\n display: block;\\n top: 10px;\\n width: 100%;\\n height: 100%;\\n margin-left: auto;\\n margin-right: auto;\\n text-align: center;\\n}\\n\\n.bottomnav-item {\\n position: relative;\\n display: inline-block;\\n width: 65px;\\n height: 50px;\\n margin-top: 6px;\\n color: rgb(150, 150, 150);\\n text-align: center;\\n font-size: 0.8em;\\n}\\n\\n.bottomnav-item a {\\n color: rgb(150, 150, 150);\\n}\\n\\n.bottomnav-item a:hover {\\n color: rgb(200, 200, 200);\\n text-decoration: none;\\n}\", \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://asatruphp/./app/resources/sass/app.scss?./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js"); /***/ }),