├── .gitignore ├── README.md ├── Thumbnail ├── 1.png ├── 2.png ├── 3.png ├── 4.png └── 5.png └── bot_manager_web ├── __init__.py ├── http_handler.py ├── reply.py ├── statics ├── images │ ├── avatars │ │ ├── 0.jpg │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── default.png │ └── logo.svg ├── scripts │ ├── captcha.js │ ├── common.js │ ├── extras.1.1.0.min.js │ ├── form.js │ ├── shards-dashboards.1.1.0.js │ ├── shards-dashboards.1.1.0.js.map │ └── shards-dashboards.1.1.0.min.js └── styles │ ├── accents │ ├── danger.1.1.0.css │ ├── danger.1.1.0.min.css │ ├── info.1.1.0.css │ ├── info.1.1.0.min.css │ ├── secondary.1.1.0.css │ ├── secondary.1.1.0.min.css │ ├── success.1.1.0.css │ ├── success.1.1.0.min.css │ ├── warning.1.1.0.css │ └── warning.1.1.0.min.css │ ├── common.css │ ├── extras.1.1.0.min.css │ ├── form.css │ ├── material.css │ ├── scss │ ├── _alert.scss │ ├── _badge.scss │ ├── _button-group.scss │ ├── _buttons.scss │ ├── _card.scss │ ├── _custom-forms.scss │ ├── _custom-sliders.scss │ ├── _dropdown.scss │ ├── _icons.scss │ ├── _images.scss │ ├── _input-group.scss │ ├── _list-group.scss │ ├── _navbar.scss │ ├── _overrides.scss │ ├── _reboot.scss │ ├── _utilities.scss │ ├── _variables.scss │ ├── accent-variations │ │ ├── danger.scss │ │ ├── info.scss │ │ ├── secondary.scss │ │ ├── success.scss │ │ └── warning.scss │ ├── blocks │ │ ├── _main-content.scss │ │ ├── _main-footer.scss │ │ ├── _main-navbar.scss │ │ ├── _main-sidebar.scss │ │ └── _page-header.scss │ ├── components │ │ ├── _card-post.scss │ │ └── _error.scss │ ├── plugins │ │ └── _quill.scss │ ├── shards-dashboards.scss │ ├── templates │ │ ├── _blog-add-new-post.scss │ │ ├── _blog-overview.scss │ │ └── _common.scss │ └── utilities │ │ ├── _borders.scss │ │ ├── _general.scss │ │ └── _text.scss │ ├── shards-dashboards.1.1.0.css │ └── shards-dashboards.1.1.0.min.css ├── templates ├── group_list.html ├── group_services.html ├── login.html ├── manage.html ├── service_groups.html ├── service_list.html └── share │ ├── after_load.html │ ├── article.html │ ├── bare_base.html │ ├── base.html │ ├── error.html │ ├── form.html │ ├── imports.html │ ├── main_footer.html │ ├── main_header.html │ ├── main_nav_bar.html │ ├── main_slide_bar.html │ └── table.html └── view.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 简介 2 | 3 | 基于一个叫[hoshinoV2服务开关网页版.zip](https://github.com/pcrbot/plugins-for-Hoshino/tree/master/shebot/webServiceManager)(作者 @shewinder ) 改出来的玩意儿,web管理hoshino的service开关的东西。 4 | 5 | ## 安装 6 | 7 | 1. 前略装好hoshinobot。步骤参考[hoshino文档](https://github.com/Ice-Cirno/HoshinoBot)。 8 | 9 | 2. 整个`bot_manager_web`目录塞进`hoshino/modules`目录下面。 10 | 11 | 3. 在`hoshino/config/__bot__.py`文件中添加模块引用。MODULES_ON 这个字典中添加一行`'bot_manager_web'`。 12 | 13 | 4. 修改配置信息(密码请务必修改,避免造成信息泄露!) 14 | 15 | BOT_MANAGER_WEB_PASSWORD 16 | 17 | - 环境变量。环境变量中`BOT_MANAGER_WEB_PASSWORD`值设置为想要的密码。 18 | - 如果不想用环境变量,则可以修改`hoshino/modules/bot_manager_web/view.py`中的`PASSWORD`后面值修改成你想要的密码。 19 | 20 | PUBLIC_ADDRESS 21 | 22 | 这个一般不用管,直接引用的hoshino的配置。如果要修改的话 23 | 24 | - 环境变量。环境变量中`PUBLIC_ADDRESS`值设置为想要的密码。 25 | - 如果不想用环境变量,则可以修改`hoshino/modules/bot_manager_web/reply.py`中的`PUBLIC_ADDRESS`后面值修改成你想要的url。 26 | 27 | ## 使用 28 | 29 | 访问`https://bcr.yourdomain.com:/manage` 30 | 31 | 输入上面文件里设定的密码登录(至于为啥没有用户名,反正只有一个人会去登录的东西要什么用户名!) 32 | 33 | 然后是进入服务里管理群功能开关,还是进入群列表管理服务功能开关,正常人都能看懂吧。 34 | 35 | PS: 注销按钮我也不知道为啥要存在,想了想也没啥意义就没做了。 36 | 37 | PPS: 还有部分垃圾文件懒得看了,体积也不算太过夸张懒得抽了,有人有空可以抽一抽。 38 | 39 | PPPS:友情提示!使用云服务器请确认对应端口在云服务器中是否开放!使用windows服务器请在服务器的防火墙中确认对应端口是否开放! 40 | 41 | PPPPS: 端口请查看你的hoshine的文件 ```config/__bot__.py``` 里的PORT参数设置的是多少。 42 | 43 | ## 图示 44 | 45 | ![图1](Thumbnail/1.png) 46 | ![图2](Thumbnail/2.png) 47 | ![图3](Thumbnail/3.png) 48 | ![图4](Thumbnail/4.png) 49 | ![图5](Thumbnail/5.png) 50 | -------------------------------------------------------------------------------- /Thumbnail/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pcrbot/HosBotManagerWeb/662fb139ed474770b1bcc6409b27df13ad9535ed/Thumbnail/1.png -------------------------------------------------------------------------------- /Thumbnail/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pcrbot/HosBotManagerWeb/662fb139ed474770b1bcc6409b27df13ad9535ed/Thumbnail/2.png -------------------------------------------------------------------------------- /Thumbnail/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pcrbot/HosBotManagerWeb/662fb139ed474770b1bcc6409b27df13ad9535ed/Thumbnail/3.png -------------------------------------------------------------------------------- /Thumbnail/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pcrbot/HosBotManagerWeb/662fb139ed474770b1bcc6409b27df13ad9535ed/Thumbnail/4.png -------------------------------------------------------------------------------- /Thumbnail/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pcrbot/HosBotManagerWeb/662fb139ed474770b1bcc6409b27df13ad9535ed/Thumbnail/5.png -------------------------------------------------------------------------------- /bot_manager_web/__init__.py: -------------------------------------------------------------------------------- 1 | import nonebot 2 | from .view import switcher 3 | 4 | app = nonebot.get_bot().server_app 5 | app.register_blueprint(switcher) 6 | -------------------------------------------------------------------------------- /bot_manager_web/http_handler.py: -------------------------------------------------------------------------------- 1 | import jinja2 2 | import os 3 | import random 4 | 5 | template_folder = os.path.join(os.path.dirname(__file__), 'templates') 6 | env = jinja2.Environment( 7 | loader=jinja2.FileSystemLoader(template_folder), 8 | enable_async=True 9 | ) 10 | 11 | 12 | async def render_template(template, **kwargs): 13 | t = env.get_template(template) 14 | return await t.render_async(**kwargs) 15 | 16 | 17 | def get_random_str(num: int): 18 | salt = '' 19 | for i in range(num): 20 | salt += random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ') 21 | return salt 22 | -------------------------------------------------------------------------------- /bot_manager_web/reply.py: -------------------------------------------------------------------------------- 1 | import os 2 | import nonebot 3 | from hoshino.config import HOST, PORT 4 | 5 | # 私聊机器人“bot设置”返回的网址基础域名,默认是从hoshino的配置中读取 6 | PUBLIC_ADDRESS = os.environ.get('PUBLIC_ADDRESS') if os.environ.get('PUBLIC_ADDRESS') else f"http://{HOST}:{PORT}" 7 | 8 | bot = nonebot.get_bot() 9 | 10 | 11 | @bot.on_message('private') 12 | async def setting(ctx): 13 | message = ctx['raw_message'] 14 | if message == 'bot设置': 15 | await bot.send(ctx, f'{PUBLIC_ADDRESS}/manage', at_sender=False) 16 | -------------------------------------------------------------------------------- /bot_manager_web/statics/images/avatars/0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pcrbot/HosBotManagerWeb/662fb139ed474770b1bcc6409b27df13ad9535ed/bot_manager_web/statics/images/avatars/0.jpg -------------------------------------------------------------------------------- /bot_manager_web/statics/images/avatars/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pcrbot/HosBotManagerWeb/662fb139ed474770b1bcc6409b27df13ad9535ed/bot_manager_web/statics/images/avatars/1.jpg -------------------------------------------------------------------------------- /bot_manager_web/statics/images/avatars/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pcrbot/HosBotManagerWeb/662fb139ed474770b1bcc6409b27df13ad9535ed/bot_manager_web/statics/images/avatars/2.jpg -------------------------------------------------------------------------------- /bot_manager_web/statics/images/avatars/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pcrbot/HosBotManagerWeb/662fb139ed474770b1bcc6409b27df13ad9535ed/bot_manager_web/statics/images/avatars/3.jpg -------------------------------------------------------------------------------- /bot_manager_web/statics/images/avatars/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pcrbot/HosBotManagerWeb/662fb139ed474770b1bcc6409b27df13ad9535ed/bot_manager_web/statics/images/avatars/default.png -------------------------------------------------------------------------------- /bot_manager_web/statics/images/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bot_manager_web/statics/scripts/captcha.js: -------------------------------------------------------------------------------- 1 | //短信验证码校验 2 | function checkSmsCode() { 3 | const phone = $('#phone').val(); 4 | const code = $('#sms_code').val(); 5 | let check_result = false; 6 | $.ajax({ 7 | 8 | async: false, 9 | type: "get", 10 | url: "/accounts/sms_check", 11 | data: "phone=" + phone + "&code=" + code, 12 | success: function (msg) { 13 | console.log(msg); 14 | if (msg.code === 200) { 15 | check_result = true; 16 | } else { 17 | set_msg(msg.message); 18 | } 19 | }, 20 | error: function (res) { 21 | console.log(res.status) 22 | } 23 | }); 24 | console.info(check_result); 25 | return check_result 26 | } 27 | 28 | 29 | //验证图形验证码 30 | function checkImageCaptcha() { 31 | let check_result = false; 32 | const captcha = $('#captcha'); 33 | if (captcha.val().length > 0) { 34 | const data = { 35 | "csrfmiddlewaretoken": $('[name="csrfmiddlewaretoken"]').val(), 36 | "uuid": $('#captcha_uuid').val(), 37 | "code": captcha.val(), 38 | }; 39 | $.ajax({ 40 | async: false, 41 | type: 'POST', 42 | url: "/captcha/verify/", 43 | data: data, 44 | success: function (data) { 45 | if (data.code === 200) { 46 | console.info("image captcha pass"); 47 | check_result = true; 48 | return true; 49 | } else { 50 | addErrorMsg('captcha', "图形验证码错误"); 51 | alert("图形验证码错误!"); 52 | console.info("invalid image captcha"); 53 | $('#captcha').focus(); 54 | } 55 | }, 56 | error: function () { 57 | alert("图形验证码验证服务器出错!"); 58 | addErrorMsg('captcha', "图形验证码验证服务器出错"); 59 | console.info("图形验证码验证服务器出错"); 60 | $('#captcha').focus(); 61 | 62 | } 63 | }) 64 | } else { 65 | addErrorMsg('captcha', "图形验证码不能为空"); 66 | alert("图形验证码不能为空") 67 | } 68 | return check_result; 69 | } 70 | 71 | function get_sms_code() { 72 | const image_correct = checkImageCaptcha(); 73 | if (image_correct) { 74 | $.ajax({ 75 | type: "POST", 76 | url: "/accounts/sms_send", 77 | data: { 78 | "phone": $("#phone").val(), 79 | "csrfmiddlewaretoken": $('[name="csrfmiddlewaretoken"]').val(), 80 | }, 81 | success: function (msg) { 82 | console.info(msg); 83 | if (msg.message === "OK") { 84 | set_msg("验证码发送成功"); 85 | } else { 86 | set_msg(msg.message); 87 | } 88 | }, 89 | error: function (res) { 90 | set_msg("手机验证码验证出错,状态 " + res.code); 91 | } 92 | }); 93 | } 94 | } 95 | 96 | 97 | $(document).ready(function () { 98 | $('.captcha').click(function () { 99 | const uuid = guid(); 100 | $('#captcha_image').attr('src', "/captcha/gen/" + uuid + "/"); 101 | $('#captcha_uuid').val(uuid); 102 | }); 103 | // $("#captcha").change(function () { 104 | // checkImageCaptcha(); 105 | // }); 106 | // $('#sms_code').change(function () { 107 | // checkSmsCode(); 108 | // }); 109 | const msg_string = $("#msg").html(); 110 | if (msg_string.length > 0) { 111 | alert(msg_string); 112 | } 113 | }); 114 | $(document).ready(function () { 115 | $('.captcha').click(); 116 | }); -------------------------------------------------------------------------------- /bot_manager_web/statics/scripts/common.js: -------------------------------------------------------------------------------- 1 | function getCookie(name) { 2 | const strCookie = document.cookie; 3 | const arrCookie = strCookie.split("; "); 4 | for (let i = 0; i < arrCookie.length; i++) { 5 | const arr = arrCookie[i].split("="); 6 | if (arr[0] === name) { 7 | return arr[1] 8 | } 9 | } 10 | return "" 11 | } 12 | 13 | function guid() { 14 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 15 | const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); 16 | return v.toString(16); 17 | }); 18 | } 19 | 20 | function set_msg(msg_text) { 21 | alert(msg_text); 22 | $('#msg').html(msg_text); 23 | } 24 | 25 | function getQueryVariable(variable) { 26 | const query = window.location.search.substring(1); 27 | const vars = query.split("&"); 28 | for (let i = 0; i < vars.length; i++) { 29 | const pair = vars[i].split("="); 30 | if (pair[0] === variable) { 31 | return pair[1]; 32 | } 33 | } 34 | return false; 35 | } 36 | 37 | function assembleQueryString(paramsArr) { 38 | const q = []; 39 | for (const k in paramsArr) { 40 | if (paramsArr.hasOwnProperty(k)) { 41 | q.push(k + "=" + paramsArr[k]); 42 | } 43 | } 44 | return q.join("&"); 45 | } 46 | 47 | 48 | function redirectWithParams(keepParamsList, addParamsArr) { 49 | const finalParams = {}; 50 | for (const k of keepParamsList) { 51 | finalParams[k] = getQueryVariable(k) 52 | } 53 | for (const k in addParamsArr) { 54 | if (addParamsArr.hasOwnProperty(k)) { 55 | finalParams[k] = addParamsArr[k] 56 | } 57 | } 58 | 59 | window.location.href = window.location.pathname + "?" + assembleQueryString(finalParams) 60 | } 61 | 62 | function coloring_systolic(input_id) { 63 | const input_item = $("#" + input_id); 64 | const s = Number(input_item.val()); 65 | if (s > 90) { 66 | input_item.addClass("bloodPressureHigh"); 67 | } else if (s < 60) { 68 | input_item.addClass("bloodPressureLow"); 69 | } 70 | } 71 | 72 | function coloring_diastolic(input_id) { 73 | const input_item = $("#" + input_id); 74 | const s = Number(input_item.val()); 75 | if (s > 140) { 76 | input_item.addClass("bloodPressureHigh"); 77 | } else if (s < 90) { 78 | input_item.addClass("bloodPressureLow"); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /bot_manager_web/statics/scripts/extras.1.1.0.min.js: -------------------------------------------------------------------------------- 1 | "use strict";!function(e){jQuery(document).ready(function(){var t={getItem:function(e){return e&&decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*"+encodeURIComponent(e).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1"))||null},setItem:function(e,t,o,s,a,n){if(!e||/^(?:expires|max\-age|path|domain|secure)$/i.test(e))return!1;var i="";if(o)switch(o.constructor){case Number:i=o===1/0?"; expires=Fri, 31 Dec 9999 23:59:59 GMT":"; max-age="+o;break;case String:i="; expires="+o;break;case Date:i="; expires="+o.toUTCString()}return document.cookie=encodeURIComponent(e)+"="+encodeURIComponent(t)+i+(a?"; domain="+a:"")+(s?"; path="+s:"")+(n?"; secure":""),!0},removeItem:function(e,t,o){return!!this.hasItem(e)&&(document.cookie=encodeURIComponent(e)+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT"+(o?"; domain="+o:"")+(t?"; path="+t:""),!0)},hasItem:function(e){return!(!e||/^(?:expires|max\-age|path|domain|secure)$/i.test(e))&&new RegExp("(?:^|;\\s*)"+encodeURIComponent(e).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=").test(document.cookie)},keys:function(){for(var e=document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g,"").split(/\s*(?:\=[^;]*)?;\s*/),t=e.length,o=0;o>16&255,o>>8&255,255&o].join(",")+","+t+")"}e("#social-share").sharrre({share:{facebook:!0,twitter:!0},buttons:{facebook:{layout:"button_count",action:"like"},twitter:{count:"horizontal",via:"DesignRevision",hashtags:"bootstrap,uikit"}},enableTracking:!0,enableHover:!1,enableCounter:!1}),e(".color-switcher-toggle").click(p),e(".color-switcher .close").click(p);var m=new Date;function p(){e(".color-switcher").toggleClass("visible"),e(".color-switcher").hasClass("visible")?t.setItem("_sd_cs_visible",!0,m):t.setItem("_sd_cs_visible",!1,m)}m.setDate(m.getDate()+1),t.setItem(o,!0,m),null===t.getItem("_sd_cs_visible")&&t.setItem("_sd_cs_visible",!0,m),"false"!==t.getItem("_sd_cs_visible")&&e(".color-switcher").addClass("visible"),setTimeout(function(){e(".loading-overlay").fadeOut(250)},2e3),e(document).on("click","a.extra-action",function(t){t.preventDefault(),t.stopPropagation();var o=e(this).attr("href");!function(){try{return window.self!==window.top}catch(e){return!0}}()?window.location=o:window.parent.location=o})})}(jQuery); -------------------------------------------------------------------------------- /bot_manager_web/statics/scripts/form.js: -------------------------------------------------------------------------------- 1 | function addErrorMsg(elementNameId, msg) { 2 | $("[for=" + elementNameId + "]").after("" + msg + "") 3 | } 4 | 5 | function checkText(id) { 6 | if ($("#" + id + "").val()) { 7 | return true 8 | } else { 9 | addErrorMsg(id, "不能为空"); 10 | return false 11 | } 12 | } 13 | 14 | function checkTextNumber(id) { 15 | if (/^\d+$/.test(($("#" + id + "").val()))) { 16 | return true 17 | } else { 18 | addErrorMsg(id, "必须填写数字"); 19 | return false 20 | } 21 | } 22 | 23 | function checkTextEmail(id) { 24 | if (/^([a-zA-Z]|[0-9])(\w|-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(($("#" + id + "").val()))) { 25 | return true 26 | } else { 27 | addErrorMsg(id, "请正确填写邮箱"); 28 | return false 29 | } 30 | } 31 | 32 | function checkRadio(radioName) { 33 | let check_result = false; 34 | const obj = $("input[name=" + radioName + "]"); 35 | for (let i = 0; i < obj.length; i++) { 36 | if (obj[i].checked) { 37 | check_result = true; 38 | } 39 | } 40 | if (!check_result) { 41 | addErrorMsg(radioName, "必选"); 42 | } 43 | return check_result 44 | } 45 | 46 | function cleanErrorMsg() { 47 | $(".errorMsg").remove(); 48 | } 49 | -------------------------------------------------------------------------------- /bot_manager_web/statics/scripts/shards-dashboards.1.1.0.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Shards Dashboards v1.1.0 3 | * Copyright 2011-2018 DesignRevision 4 | * SEE LICENSE FILE 5 | */ 6 | (function (global, factory) { 7 | typeof exports === 'object' && typeof module !== 'undefined' ? factory() : 8 | typeof define === 'function' && define.amd ? define(factory) : 9 | (factory()); 10 | }(this, (function () { 'use strict'; 11 | 12 | if (typeof Chart === 'undefined') { 13 | throw new Error('Shards Dashboard requires the Chart.js library in order to function properly.'); 14 | } 15 | 16 | window.ShardsDashboards = window.ShardsDashboards ? window.ShardsDashboards : {}; 17 | 18 | $.extend($.easing, { 19 | easeOutSine: function easeOutSine(x, t, b, c, d) { 20 | return c * Math.sin(t / d * (Math.PI / 2)) + b; 21 | } 22 | }); 23 | 24 | /** 25 | * Chart.js - Line Chart with Vertical Line 26 | */ 27 | Chart.defaults.LineWithLine = Chart.defaults.line; 28 | Chart.controllers.LineWithLine = Chart.controllers.line.extend({ 29 | draw: function draw(ease) { 30 | Chart.controllers.line.prototype.draw.call(this, ease); 31 | if (this.chart.tooltip._active && this.chart.tooltip._active.length) { 32 | var activePoint = this.chart.tooltip._active[0], 33 | ctx = this.chart.ctx, 34 | x = activePoint.tooltipPosition().x, 35 | topY = this.chart.scales['y-axis-0'].top, 36 | bottomY = this.chart.scales['y-axis-0'].bottom; 37 | 38 | // Draw the line 39 | ctx.save(); 40 | ctx.beginPath(); 41 | ctx.moveTo(x, topY); 42 | ctx.lineTo(x, bottomY); 43 | ctx.lineWidth = 0.5; 44 | ctx.strokeStyle = '#ddd'; 45 | ctx.stroke(); 46 | ctx.restore(); 47 | } 48 | } 49 | }); 50 | 51 | $(document).ready(function () { 52 | 53 | /** 54 | * Dropdown adjustments 55 | */ 56 | 57 | var slideConfig = { 58 | duration: 270, 59 | easing: 'easeOutSine' 60 | }; 61 | 62 | // Add dropdown animations when toggled. 63 | $(':not(.main-sidebar--icons-only) .dropdown').on('show.bs.dropdown', function () { 64 | $(this).find('.dropdown-menu').first().stop(true, true).slideDown(slideConfig); 65 | }); 66 | 67 | $(':not(.main-sidebar--icons-only) .dropdown').on('hide.bs.dropdown', function () { 68 | $(this).find('.dropdown-menu').first().stop(true, true).slideUp(slideConfig); 69 | }); 70 | 71 | /** 72 | * Sidebar toggles 73 | */ 74 | $('.toggle-sidebar').click(function (e) { 75 | $('.main-sidebar').toggleClass('open'); 76 | }); 77 | }); 78 | 79 | }))); 80 | 81 | //# sourceMappingURL=shards-dashboards.1.1.0.js.map 82 | -------------------------------------------------------------------------------- /bot_manager_web/statics/scripts/shards-dashboards.1.1.0.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"names":[],"mappings":"","sources":["shards-dashboards.1.1.0.js"],"sourcesContent":["/*!\n* Shards Dashboards v1.1.0\n* Copyright 2011-2018 DesignRevision\n* SEE LICENSE FILE\n*/\n(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n\ttypeof define === 'function' && define.amd ? define(factory) :\n\t(factory());\n}(this, (function () { 'use strict';\n\nif (typeof Chart === 'undefined') {\n throw new Error('Shards Dashboard requires the Chart.js library in order to function properly.');\n}\n\nwindow.ShardsDashboards = window.ShardsDashboards ? window.ShardsDashboards : {};\n\n$.extend($.easing, {\n easeOutSine: function easeOutSine(x, t, b, c, d) {\n return c * Math.sin(t / d * (Math.PI / 2)) + b;\n }\n});\n\n/**\n * Chart.js - Line Chart with Vertical Line\n */\nChart.defaults.LineWithLine = Chart.defaults.line;\nChart.controllers.LineWithLine = Chart.controllers.line.extend({\n draw: function draw(ease) {\n Chart.controllers.line.prototype.draw.call(this, ease);\n if (this.chart.tooltip._active && this.chart.tooltip._active.length) {\n var activePoint = this.chart.tooltip._active[0],\n ctx = this.chart.ctx,\n x = activePoint.tooltipPosition().x,\n topY = this.chart.scales['y-axis-0'].top,\n bottomY = this.chart.scales['y-axis-0'].bottom;\n\n // Draw the line\n ctx.save();\n ctx.beginPath();\n ctx.moveTo(x, topY);\n ctx.lineTo(x, bottomY);\n ctx.lineWidth = 0.5;\n ctx.strokeStyle = '#ddd';\n ctx.stroke();\n ctx.restore();\n }\n }\n});\n\n$(document).ready(function () {\n\n /**\n * Dropdown adjustments\n */\n\n var slideConfig = {\n duration: 270,\n easing: 'easeOutSine'\n };\n\n // Add dropdown animations when toggled.\n $(':not(.main-sidebar--icons-only) .dropdown').on('show.bs.dropdown', function () {\n $(this).find('.dropdown-menu').first().stop(true, true).slideDown(slideConfig);\n });\n\n $(':not(.main-sidebar--icons-only) .dropdown').on('hide.bs.dropdown', function () {\n $(this).find('.dropdown-menu').first().stop(true, true).slideUp(slideConfig);\n });\n\n /**\n * Sidebar toggles\n */\n $('.toggle-sidebar').click(function (e) {\n $('.main-sidebar').toggleClass('open');\n });\n});\n\n})));\n"],"file":"shards-dashboards.1.1.0.js"} -------------------------------------------------------------------------------- /bot_manager_web/statics/scripts/shards-dashboards.1.1.0.min.js: -------------------------------------------------------------------------------- 1 | !function(t,o){"object"==typeof exports&&"undefined"!=typeof module?o():"function"==typeof define&&define.amd?define(o):o()}(0,function(){"use strict";if("undefined"==typeof Chart)throw new Error("Shards Dashboard requires the Chart.js library in order to function properly.");window.ShardsDashboards=window.ShardsDashboards?window.ShardsDashboards:{},$.extend($.easing,{easeOutSine:function(t,o,e,i,n){return i*Math.sin(o/n*(Math.PI/2))+e}}),Chart.defaults.LineWithLine=Chart.defaults.line,Chart.controllers.LineWithLine=Chart.controllers.line.extend({draw:function(t){if(Chart.controllers.line.prototype.draw.call(this,t),this.chart.tooltip._active&&this.chart.tooltip._active.length){var o=this.chart.tooltip._active[0],e=this.chart.ctx,i=o.tooltipPosition().x,n=this.chart.scales["y-axis-0"].top,r=this.chart.scales["y-axis-0"].bottom;e.save(),e.beginPath(),e.moveTo(i,n),e.lineTo(i,r),e.lineWidth=.5,e.strokeStyle="#ddd",e.stroke(),e.restore()}}}),$(document).ready(function(){var t={duration:270,easing:"easeOutSine"};$(":not(.main-sidebar--icons-only) .dropdown").on("show.bs.dropdown",function(){$(this).find(".dropdown-menu").first().stop(!0,!0).slideDown(t)}),$(":not(.main-sidebar--icons-only) .dropdown").on("hide.bs.dropdown",function(){$(this).find(".dropdown-menu").first().stop(!0,!0).slideUp(t)}),$(".toggle-sidebar").click(function(t){$(".main-sidebar").toggleClass("open")})})}); -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/common.css: -------------------------------------------------------------------------------- 1 | .bloodPressureHigh { 2 | color: red; 3 | } 4 | 5 | .bloodPressureLow { 6 | color: #33CC00; 7 | } 8 | 9 | .switchButton { 10 | display: inline-block; 11 | width: 70px; 12 | } 13 | 14 | .on { 15 | background-color: lawngreen; 16 | } 17 | 18 | .off { 19 | background-color: gray; 20 | } -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/extras.1.1.0.min.css: -------------------------------------------------------------------------------- 1 | .animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}@-webkit-keyframes bounceIn{20%,40%,60%,80%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes bounceIn{20%,40%,60%,80%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.bounceIn{-webkit-animation-duration:.75s;animation-duration:.75s;-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes slideInUp{from{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInUp{from{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInUp{-webkit-animation-name:slideInUp;animation-name:slideInUp}@-webkit-keyframes pulse{from{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes pulse{from{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.pulse{-webkit-animation-name:pulse;animation-name:pulse}.promo-popup{display:none;opacity:0;position:fixed;right:24px;bottom:0;background:#fff;box-shadow:0 0 10px rgba(24,29,39,.1),0 15px 30px rgba(24,29,39,.1),0 5px 10px rgba(24,29,39,.05);z-index:2000;overflow:hidden;max-width:430px;border-radius:7px;-webkit-transform:translate(-100%,-100%);transform:translate(-100%,-100%);transition:bottom 280ms ease-in-out,-webkit-transform 280ms ease-in-out;transition:transform 280ms ease-in-out,bottom 280ms ease-in-out;transition:transform 280ms ease-in-out,bottom 280ms ease-in-out,-webkit-transform 280ms ease-in-out}.promo-popup .up{display:none}.promo-popup.slideInUp{bottom:30px;-webkit-transform:translate(0,0);transform:translate(0,0);display:block;opacity:1}.promo-popup.bounceIn{bottom:30px;display:block}.promo-popup.hidden{bottom:-156px;right:24px;opacity:1}.promo-popup.hidden img{-webkit-transform:translateX(-100%);transform:translateX(-100%)}.promo-popup.hidden .pp-intro-bar{padding-left:20px}.promo-popup.hidden .pp-intro-bar h2:hover,.promo-popup.hidden .pp-intro-bar:hover{cursor:pointer}.promo-popup.hidden .up{display:block}.promo-popup.hidden .close{display:none}.promo-popup.visible{-webkit-transform:translateX(0);transform:translateX(0)}.promo-popup img{position:absolute;left:0;bottom:0;height:100%;top:10px;box-shadow:0 0 15px rgba(0,0,0,.2);z-index:1;transition:-webkit-transform 280ms ease-in-out;transition:transform 280ms ease-in-out;transition:transform 280ms ease-in-out,-webkit-transform 280ms ease-in-out}.promo-popup .pp-intro-bar{background:#2d53fe;color:#fff;text-transform:uppercase;font-weight:500;font-size:11px;letter-spacing:3px;padding:10px 0;padding-left:172px;position:relative;transition:padding 280ms ease-in-out;line-height:1.5}.promo-popup .pp-intro-bar .close,.promo-popup .pp-intro-bar .up{position:absolute;bottom:0;right:0;top:0;line-height:36px;width:32px;text-align:center;transition:all 250ms ease-in-out;color:#fff}.promo-popup .pp-intro-bar .close i,.promo-popup .pp-intro-bar .up i{opacity:.7;font-size:17px;transition:all 250ms ease-in-out}.promo-popup .pp-intro-bar .close:hover,.promo-popup .pp-intro-bar .up:hover{cursor:pointer;background:#143efe}.promo-popup .pp-intro-bar .close:hover i,.promo-popup .pp-intro-bar .up:hover i{opacity:1}.promo-popup .pp-intro-bar .up{line-height:26px}.promo-popup .pp-intro-bar .up i{top:11px}.promo-popup .pp-intro-bar .close i{top:0}.promo-popup .pp-inner-content{padding:22px;padding-left:172px!important}.promo-popup .pp-inner-content h2{margin-bottom:7px;font-size:24px;line-height:1}.promo-popup .pp-inner-content p{font-size:12px;margin-bottom:17px;line-height:1.4;color:#5d6f82}.promo-popup .pp-inner-content a{font-size:12px;font-weight:400;color:#fff;background:#2d53fe;padding:7px 15px;border-radius:50px;display:inline-block}.promo-popup .pp-inner-content a:hover{text-decoration:none}.color-switcher{position:fixed;left:0;bottom:30px;z-index:2001;background:#181a23;padding:20px 20px;padding-top:25px;border-radius:5px;-webkit-transform:translateX(-110%);transform:translateX(-110%);transition:left .3s ease-in-out,-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out,left .3s ease-in-out;transition:transform .3s ease-in-out,left .3s ease-in-out,-webkit-transform .3s ease-in-out;box-shadow:0 .46875rem 2.1875rem rgba(90,97,105,.1),0 .9375rem 1.40625rem rgba(90,97,105,.1),0 .25rem .53125rem rgba(90,97,105,.12),0 .125rem .1875rem rgba(90,97,105,.1)}.color-switcher.visible{-webkit-transform:translateX(0);transform:translateX(0);left:24px}.color-switcher h5{font-size:11px;font-weight:500;margin-bottom:0;line-height:1;letter-spacing:2px;color:#84899e;text-align:center;text-transform:uppercase}.color-switcher .accent-colors{display:-ms-flexbox;display:flex;padding:5px;margin:15px auto 20px auto;-ms-flex-pack:center;justify-content:center}.color-switcher .accent-colors li{display:inline-block;width:14px;height:14px;border-radius:50%;transition:-webkit-transform 180ms ease-in-out;transition:transform 180ms ease-in-out;transition:transform 180ms ease-in-out,-webkit-transform 180ms ease-in-out;text-align:center;margin:0 4px}.color-switcher .accent-colors li:hover:not(.active){cursor:pointer;-webkit-transform:scale(1.3);transform:scale(1.3)}.color-switcher .accent-colors li i{transition:opacity 180ms ease-in-out;line-height:1;color:#fff;font-size:10px;position:absolute;left:50%;top:50%;opacity:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.color-switcher .accent-colors li.active{-webkit-transform:scale(1.5);transform:scale(1.5)}.color-switcher .accent-colors li.active i{opacity:1}.color-switcher .accent-colors li.accent-primary{background-color:#007bff}.color-switcher .accent-colors li.accent-secondary{background-color:#5a6169}.color-switcher .accent-colors li.accent-success{background-color:#17c671}.color-switcher .accent-colors li.accent-info{background-color:#00b8d8}.color-switcher .accent-colors li.accent-warning{background-color:#ffb400}.color-switcher .accent-colors li.accent-danger{background-color:#c4183c}.color-switcher .actions{margin:15px 0}.color-switcher .social-actions{padding:10px 0;border-top:1px solid #2c2f44}.color-switcher .social-actions .inner-wrapper{display:table;margin:0 auto}.color-switcher .social-actions iframe{margin:5px 0 0 10px}.color-switcher #social-share{display:table;margin:0 auto}.color-switcher .sharrre .box{float:left}.color-switcher .sharrre .count{color:#444;display:block;font-size:17px;line-height:34px;height:34px;padding:4px 0;position:relative;text-align:center;text-decoration:none;width:50px;background-color:#eee;border-radius:4px}.color-switcher .sharrre .share{color:#fff;display:block;font-size:11px;height:16px;line-height:16px;margin-top:3px;padding:0;text-align:center;text-decoration:none;width:50px;background-color:#9cce39;border-radius:4px}.color-switcher .sharrre .buttons{display:block}.color-switcher .sharrre .button{float:left;margin-left:10px}.color-switcher .sharrre .button.facebook{margin-left:0}.color-switcher .close{position:absolute;right:10px;top:10px;font-size:15px;background:#2d3044;width:25px;height:25px;overflow:hidden;text-align:center;border-radius:50%;line-height:25px}.color-switcher-toggle{position:fixed;left:26px;bottom:33px;z-index:2000;width:45px;height:45px;background:#2d53fe;color:#fff;text-align:center;line-height:45px;font-size:23px;border-radius:50%;transition:color .2s ease-in-out;-webkit-animation-duration:1.5s;animation-duration:1.5s;box-shadow:0 .46875rem 2.1875rem rgba(90,97,105,.1),0 .9375rem 1.40625rem rgba(90,97,105,.1),0 .25rem .53125rem rgba(90,97,105,.12),0 .125rem .1875rem rgba(90,97,105,.1)}.color-switcher-toggle:hover{cursor:pointer;color:#fff}.color-switcher-toggle i{top:3px}.social-wrapper{position:relative}.social-wrapper .loading-overlay{position:absolute;top:0;left:0;right:0;bottom:0;background:#181a23}.social-wrapper .spinner{position:absolute;top:50%;left:50%;margin-left:-10px;margin-top:-10px}.spinner{height:20px;width:20px;-webkit-animation:rotate .8s infinite linear;animation:rotate .8s infinite linear;border:2px solid #84899e;border-right-color:transparent;border-radius:50%}@-webkit-keyframes rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@media (max-width:860px){.color-switcher,.color-switcher-toggle{display:none!important}}@media (max-width:500px){.promo-popup{left:10px;right:10px;bottom:10px!important}.promo-popup h2{font-size:22px!important;font-weight:500;letter-spacing:0}.promo-popup.hidden{bottom:-158px!important;left:10px!important;right:10px!important}.promo-popup.hidden .pp-intro-bar{padding-left:20px!important}.promo-popup img{left:-80px}.promo-popup .pp-inner-content,.promo-popup .pp-intro-bar{padding-left:85px!important}} -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/form.css: -------------------------------------------------------------------------------- 1 | .addRedStar:before { 2 | content: '*'; 3 | color: red; 4 | font-size: 18px; 5 | } 6 | .errorMsg{ 7 | color: red; 8 | margin-left: 10px; 9 | } -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/material.css: -------------------------------------------------------------------------------- 1 | /* fallback */ 2 | @font-face { 3 | font-family: 'Material Icons'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: url(https://cdn.bootcdn.net/ajax/libs/material-design-icons/3.0.1/iconfont/MaterialIcons-Regular.woff2) format('woff2'); 7 | } 8 | 9 | .material-icons { 10 | font-family: 'Material Icons'; 11 | font-weight: normal; 12 | font-style: normal; 13 | font-size: 24px; 14 | line-height: 1; 15 | letter-spacing: normal; 16 | text-transform: none; 17 | display: inline-block; 18 | white-space: nowrap; 19 | word-wrap: normal; 20 | direction: ltr; 21 | -webkit-font-feature-settings: 'liga'; 22 | -webkit-font-smoothing: antialiased; 23 | } -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_alert.scss: -------------------------------------------------------------------------------- 1 | // Alert Adjustments 2 | 3 | // Alternate style for the accent color 4 | .alert-accent { 5 | color: lighten($accent-color, 48%); 6 | background-color: $accent-color; 7 | 8 | .alert-link { 9 | color: lighten($accent-color, 48%); 10 | } 11 | } 12 | 13 | .alert-dismissible .close { 14 | padding-top: 0.5rem; 15 | padding-bottom: 0.5rem; 16 | } 17 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_badge.scss: -------------------------------------------------------------------------------- 1 | // Badge Adjustments 2 | 3 | // Accent color badge variations 4 | .badge-accent { 5 | @include badge-variant($accent-color); 6 | } 7 | 8 | // Accent color outline badge variation 9 | .badge-outline-accent { 10 | background: none; 11 | border: 1px solid $accent-color; 12 | color: $accent-color; 13 | } 14 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_button-group.scss: -------------------------------------------------------------------------------- 1 | // Button group 2 | 3 | // Adjust button groups icons 4 | .btn-group-sm i { 5 | transform: scale(1.3); 6 | } 7 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_buttons.scss: -------------------------------------------------------------------------------- 1 | // Buttons Adjustments 2 | 3 | // White and black button adjustments specific to Shards Dashboard. 4 | // If you want to use the default Shards buttons just comment the 5 | // styles below. 6 | 7 | .btn-white, 8 | .btn-black { 9 | // Set the defaults to use the accent color. 10 | &:not([disabled]):not(.disabled):active, 11 | &:not([disabled]):not(.disabled).active { 12 | box-shadow: none !important; 13 | background-color: $accent-color; 14 | border-color: $accent-color; 15 | color: $white; 16 | 17 | + .btn { 18 | border-left: 1px solid $accent-color; 19 | } 20 | } 21 | 22 | &:hover { 23 | background: $white; 24 | border-color: $white; 25 | box-shadow: 0px 0.125rem 0.625rem rgba($reagent-gray, .2), 26 | 0 0.0625rem 0.125rem rgba($reagent-gray, .3); 27 | } 28 | } 29 | 30 | // White button accent color modifiers. 31 | // Selector specificity to override existing active state. 32 | .btn.btn-white { 33 | border: 1px solid $border-color; 34 | color: $fiord-blue; 35 | 36 | @mixin btn-active-modifier($color, $value) { 37 | &:not([disabled]):not(.disabled).active-#{$color} { 38 | &.active, 39 | &:active { 40 | background-color: $value; 41 | border-color: $value; 42 | color: color-yiq($value); 43 | 44 | & + .btn { 45 | border-left: 1px solid red; 46 | } 47 | } 48 | } 49 | } 50 | 51 | // Existent theme colors 52 | @each $color, $value in $theme-colors { 53 | @include btn-active-modifier($color, $value); 54 | } 55 | } 56 | 57 | 58 | // Button variation for the accent color. 59 | .btn-accent { 60 | @include button-variant($accent-color); 61 | } 62 | 63 | // Outline button variation for the accent color. 64 | .btn-outline-accent { 65 | @include button-outline-variant($accent-color); 66 | } 67 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_card.scss: -------------------------------------------------------------------------------- 1 | // Card adjustments 2 | 3 | // Block handles 4 | .card-header { 5 | h1, h2, h3, h4, h5, h6 { 6 | font-weight: $card-headings-font-weight; 7 | } 8 | } 9 | 10 | // Small "Full Report" cards element adjustments 11 | .card .view-report { 12 | margin-top: auto; 13 | margin-bottom: auto; 14 | font-size: $card-view-report-font-size; 15 | 16 | a { 17 | color: $card-view-report-link-color; 18 | 19 | &:hover { 20 | color: $card-view-report-link-color-hover; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_custom-forms.scss: -------------------------------------------------------------------------------- 1 | // Custom forms adjustments 2 | 3 | .custom-select-sm { 4 | font-size: $font-size-sm; 5 | border-radius: $btn-border-radius; 6 | } 7 | 8 | .custom-select-lg { 9 | border-radius: $btn-border-radius; 10 | } 11 | 12 | // Adjust the custom control line height. 13 | .custom-control { 14 | line-height: 1.5rem; 15 | } 16 | 17 | 18 | // Adjust custom controls disabled states. 19 | 20 | // Custom checkboxes 21 | .custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label { 22 | &::after { 23 | border-color: $custom-control-disabled-color; 24 | } 25 | } 26 | 27 | // Custom radios 28 | .custom-radio .custom-control-input:disabled:checked ~ .custom-control-label { 29 | &::after { 30 | background: $custom-control-disabled-color; 31 | } 32 | } 33 | 34 | // Custom toggle 35 | .custom-toggle .custom-control-input:checked:disabled ~ .custom-control-label { 36 | &::after { 37 | background: $custom-control-disabled-color; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_custom-sliders.scss: -------------------------------------------------------------------------------- 1 | // Custom Sliders Adjustments 2 | 3 | // Accent color slider 4 | .slider-accent .noUi-connect { 5 | background: $slider-accent-background; 6 | } 7 | 8 | .noUi-pips { 9 | font-size: $slider-pips-font-size; 10 | } 11 | 12 | .noUi-tooltip { 13 | font-size: $slider-tooltip-font-size; 14 | padding: $slider-tooltip-padding; 15 | } 16 | 17 | .noUi-horizontal { 18 | .noUi-tooltip { 19 | bottom: $slider-horizontal-tooltip-bottom; 20 | } 21 | 22 | .noUi-handle { 23 | left: $slider-horizontal-handle-left; 24 | top: $slider-horizontal-handle-top; 25 | } 26 | } 27 | 28 | .noUi-handle { 29 | width: $slider-handle-width; 30 | height: $slider-handle-height; 31 | } 32 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_dropdown.scss: -------------------------------------------------------------------------------- 1 | // Dropdown adjustments 2 | 3 | // Adjust dropdown icons 4 | .dropdown { 5 | .fa, 6 | .material-icons { 7 | color: lighten($blueish-grey, 40); 8 | margin-right: 0.25rem; 9 | } 10 | 11 | .dropdown-item { 12 | &:hover { 13 | background-color: lighten($blueish-grey, 60); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_icons.scss: -------------------------------------------------------------------------------- 1 | // Icons adjustments 2 | 3 | i.material-icons { 4 | top: 2px; 5 | } 6 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_images.scss: -------------------------------------------------------------------------------- 1 | // Images adjustments 2 | 3 | .thumbnail { 4 | border: 1px solid #D4D4D4; 5 | } 6 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_input-group.scss: -------------------------------------------------------------------------------- 1 | // Input groups adjustments 2 | 3 | // Set a min width for the input groups. 4 | // Without this some components might break (datepickers). 5 | .input-group { 6 | min-width: 7.5rem; 7 | } 8 | 9 | // Adjust the input group font size. 10 | .input-group-text { 11 | font-size: $input-font-size; 12 | } 13 | 14 | // Adjust the seamless input group - input's padding. 15 | .input-group.input-group-seamless > .form-control:not(:first-child), 16 | .input-group.input-group-seamless > .custom-select:not(:first-child) { 17 | padding-left: 1.875rem; 18 | } 19 | 20 | // Adjust the input group icons. 21 | .input-group-text i { 22 | transform: scale(1.1); 23 | 24 | &.fa { 25 | font-size: 0.75rem; 26 | } 27 | 28 | &.material-icons { 29 | top: 0; 30 | font-size: 0.8125rem; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_list-group.scss: -------------------------------------------------------------------------------- 1 | // List Group Adjustments 2 | 3 | // List group accent color variation 4 | @include list-group-item-variant($accent-color, theme-color-level($accent-color, -9), theme-color-level($accent-color, 6)); 5 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_navbar.scss: -------------------------------------------------------------------------------- 1 | // General navbar adjustments 2 | 3 | .navbar-light .navbar-brand { 4 | font-weight: $navbar-brand-font-weight; 5 | color: $navbar-brand-color; 6 | } 7 | 8 | .nav-link { 9 | font-size: $nav-link-font-size; 10 | font-weight: $nav-link-font-weight; 11 | 12 | &-icon { 13 | color: $nav-link-icon-color; 14 | 15 | @include hover-focus { 16 | color: darken($nav-link-icon-color, 10); 17 | } 18 | 19 | &__wrapper { 20 | position: relative; 21 | } 22 | 23 | i { 24 | font-size: $nav-link-icon-font-size; 25 | 26 | &.material-icons { 27 | font-size: $nav-link-material-icons-font-size; 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_overrides.scss: -------------------------------------------------------------------------------- 1 | // Shards Variables Overrides 2 | 3 | // Colors 4 | $light: #FBFBFB; 5 | $border-color: #e1e5eb; 6 | 7 | 8 | // Cards 9 | $card-cap-bg: #fff; 10 | 11 | 12 | // Typography & Fonts 13 | 14 | // Disable Google Fonts imports 15 | $enable-fonts-import: false; 16 | 17 | // Use the System UI font instead of Poppins. 18 | $font-family-poppins-first: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; 19 | 20 | $headings-color: #3D5170; 21 | $font-size-sm: 0.6875rem; 22 | 23 | 24 | // Body 25 | $body-background: #F5F6F8; 26 | 27 | $font-size-sm: 0.6875rem; 28 | $font-size-lg: 0.875rem; 29 | 30 | 31 | // Buttons 32 | $btn-font-size: 0.75rem; 33 | $btn-font-weight: 400; 34 | $btn-border-radius: 0.25rem; 35 | $btn-padding-y: 0.5625rem; 36 | $btn-padding-x: 1rem; 37 | 38 | $btn-font-size-sm: 0.6875rem; 39 | $btn-padding-y-sm: 0.4286rem; 40 | $btn-padding-x-sm: 0.875rem; 41 | 42 | $btn-border-radius-sm: $btn-border-radius; 43 | 44 | 45 | // Inputs 46 | $input-btn-padding-y: 0.4375rem; 47 | $input-btn-padding-x: 0.75rem; 48 | 49 | $input-group-padding-y: 0.75rem; 50 | $input-group-padding-x: 0.625rem; 51 | 52 | 53 | // Forms 54 | $input-font-size: 0.8125rem; 55 | 56 | $input-padding-y-sm: 0.4286rem; 57 | $input-padding-x-sm: 0.8125rem; 58 | 59 | $input-padding-y-lg: 0.8125rem; 60 | $input-padding-x-lg: 0.8125rem; 61 | $input-border-radius-lg: 0.375rem; 62 | 63 | $custom-select-line-height: 1.5; 64 | 65 | $input-padding-x-sm: 0.625rem; 66 | 67 | $input-border-radius: 0.25rem; 68 | $input-border-radius-sm: $input-border-radius; 69 | 70 | $custom-select-border-radius: $input-border-radius; 71 | 72 | $custom-file-height: calc(2.0625rem + 2px); 73 | $custom-file-border-radius: $input-border-radius; 74 | 75 | // Navs 76 | $nav-link-padding-x: 0.625rem; 77 | 78 | 79 | // Navbar brand 80 | $navbar-brand-font-size: 0.9rem; 81 | 82 | // Dropdowns 83 | $dropdown-padding-y: 10px; 84 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_reboot.scss: -------------------------------------------------------------------------------- 1 | // Reboot / Shards Improvements 2 | 3 | // HTML 4 | html { 5 | font-size: 16px; 6 | font-weight: 500; 7 | 8 | // Adjust font sizes for 144dpi+ (including retina). 9 | @media (-webkit-min-device-pixel-ratio: 1.5), 10 | (min-resolution: 144dpi) { 11 | font-size: 16px; 12 | font-weight: 400; 13 | } 14 | } 15 | 16 | 17 | // Body 18 | body { 19 | background: $body-background; 20 | font-size: 15px; 21 | font-weight: 500; 22 | 23 | @media (-webkit-min-device-pixel-ratio: 2), 24 | (min-resolution: 192dpi) { 25 | font-size: 13px; 26 | font-weight: 400; 27 | } 28 | } 29 | 30 | 31 | // Links 32 | a { 33 | color: $accent-color; 34 | 35 | @include hover { 36 | color: darken($accent-color, 15%); 37 | } 38 | } 39 | 40 | 41 | // Labels 42 | label { 43 | font-weight: 400; 44 | } 45 | 46 | 47 | // Datepicker adjustments 48 | .datepicker { 49 | font-size: .75rem; 50 | padding: 0.625rem; 51 | 52 | table tr td, 53 | table tr th { 54 | width: 1.875rem; 55 | height: 1.875rem; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_utilities.scss: -------------------------------------------------------------------------------- 1 | @import "utilities/general"; 2 | @import "utilities/text"; 3 | @import "utilities/borders"; 4 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | // Shards Dashboard Variables 2 | 3 | // New grays 4 | $fiord-blue: #3D5170 !default; 5 | $shuttle-gray: #5A6169 !default; 6 | $reagent-gray: #818EA3 !default; 7 | $mischka: #CACEDB !default; 8 | $athens-gray: #E9ECEF !default; 9 | 10 | // New grays map 11 | $new-grays: () !default; 12 | $new-grays: map-merge(( 13 | "fiord-blue" : $fiord-blue, 14 | "shuttle-gray": $shuttle-gray, 15 | "reagent-gray": $reagent-gray, 16 | "mischka" : $mischka, 17 | "athens-gray" : $athens-gray, 18 | ), $new-grays); 19 | 20 | 21 | // Accent color 22 | // Override this color and recompile the package to quickly change 23 | // the general accent color theme. 24 | $accent-color: theme-color('primary') !default; 25 | 26 | 27 | // Text color adjustments 28 | $text-light-color: $reagent-gray !default; 29 | 30 | // Text font weights 31 | $text-semibold-font-weight: 400 !default; 32 | 33 | // Fonts 34 | $font-family-system-first: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !default; 35 | $font-family-roboto-mono-first: "Roboto Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default; 36 | $font-family-roboto-first: Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif !default; 37 | 38 | 39 | // Icons 40 | $icon-color: $mischka !default; 41 | 42 | $clear-white: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTE5IDYuNDFMMTcuNTkgNSAxMiAxMC41OSA2LjQxIDUgNSA2LjQxIDEwLjU5IDEyIDUgMTcuNTkgNi40MSAxOSAxMiAxMy40MSAxNy41OSAxOSAxOSAxNy41OSAxMy40MSAxMnoiLz4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjwvc3ZnPg==); 43 | $check-white: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPiAgICA8cGF0aCBkPSJNOSAxNi4xN0w0LjgzIDEybC0xLjQyIDEuNDFMOSAxOSAyMSA3bC0xLjQxLTEuNDF6Ii8+PC9zdmc+); 44 | 45 | 46 | // Shadows 47 | $side-shadow: 0 0.125rem 9.375rem rgba($shuttle-gray, .1), 48 | 0 0.25rem 0.5rem rgba($shuttle-gray, .12), 49 | 0 0.9375rem 1.375rem rgba($shuttle-gray, .10), 50 | 0 0.4375rem 2.1875rem rgba(#A5B6C9, .10); 51 | 52 | 53 | // Body 54 | $body-background: #F5F6F8 !default; 55 | $body-font-size: 15px !default; 56 | 57 | 58 | // Cards 59 | $card-headings-font-weight: 500 !default; 60 | 61 | // Card -> View Report Link 62 | $card-view-report-font-size: 0.75rem !default; 63 | $card-view-report-link-color: $fiord-blue !default; 64 | $card-view-report-link-color-hover: $accent-color !default; 65 | 66 | 67 | // Forms 68 | $custom-control-disabled-color: #becad6 !default; 69 | 70 | 71 | // Navbar 72 | $navbar-brand-color: $fiord-blue !default; 73 | $navbar-brand-font-weight: 500 !default; 74 | 75 | // Navbar search 76 | $navbar-search-padding-y: 23px !default; 77 | 78 | // Nav 79 | $nav-link-color: $reagent-gray !default; 80 | $nav-link-icon-color: $nav-link-color !default; 81 | $nav-link-icon-font-size: 1.25rem !default; 82 | $nav-link-material-icons-font-size: 1.5625rem !default; 83 | $nav-link-font-size: 0.8125rem !default; 84 | $nav-link-font-weight: 400 !default; 85 | 86 | 87 | // Main Navbar 88 | $main-navbar-height: 3.75rem !default; 89 | $main-navbar-box-shadow: 0 0.125rem 0.625rem rgba(90,97,105,.12) !default; 90 | $main-navbar-nav-link-min-width: 3.75rem !default; 91 | $main-navbar-actions-link-border: 1px solid #e3e6ec !default; 92 | $main-navbar-nav-link-icon-line-height: 2.5rem !default; 93 | $main-navbar-brand-font-size: 1rem !default; 94 | 95 | // Main Navbar -> Notifications 96 | $notifications-badge-padding-x: 0.375rem !default; 97 | $notifications-badge-padding-y: 0.25rem !default; 98 | $notifications-badge-font-size: 0.5rem !default; 99 | 100 | $notifications-dropdown-min-width: 25rem !default; 101 | $notifications-dropdown-item-padding-top: 0.625rem !default; 102 | $notifications-dropdown-item-padding-bottom: 0.625rem !default; 103 | $notifications-dropdown-item-border-bottom: 1px solid $border-color !default; 104 | 105 | $notifications-icon-background-color: $body-background !default; 106 | $notifications-icon-width: 2.1875rem !default; 107 | $notifications-icon-height: 2.1875rem !default; 108 | $notifications-icon-color: $text-light-color !default; 109 | $notifications-icon-line-height: 2.0625rem !default; 110 | $notifications-icon-font-size: 1.0625rem !default; 111 | $notifications-icon-box-shadow: 0 0 0 1px white, 112 | inset 0 0 3px rgba(0, 0, 0, 0.2); 113 | 114 | $notification-content-padding: 0 0.625rem !default; 115 | $notification-content-paragraph-font-size: 0.75rem !default; 116 | 117 | $notification-category-font-size: 0.5625rem !default; 118 | $notification-category-color: $reagent-gray !default; 119 | $notification-category-letter-spacing: 0.0938rem !default; 120 | 121 | // Main Navbar -> User Avatar 122 | $user-avatar-max-width: 2.5rem !default; 123 | 124 | 125 | // Header Navigation 126 | $header-navbar-icon-font-size: 0.875rem !default; 127 | $header-navbar-icon-margin-right: 0.125rem !default; 128 | 129 | $header-navbar-dropdown-nav-link-padding-right: 1.25rem !default; 130 | 131 | $header-navbar-nav-link-color: $fiord-blue !default; 132 | $header-navbar-nav-link-border: none !default; 133 | $header-navbar-nav-link-padding: 1.125rem 0 !default; 134 | $header-navbar-nav-link-margin-right: 1.25rem !default; 135 | $header-navbar-nav-link-line-height: 1 !default; 136 | $header-navbar-nav-link-border-radius: 0 !default; 137 | $header-navbar-nav-link-font-size: 0.8125rem !default; 138 | $header-navbar-nav-link-background: transparent !default; 139 | $header-navbar-nav-link-border-bottom: 1px solid transparent !default; 140 | 141 | // ahs: active, hover, show 142 | $header-navbar-nav-item-ahs-border-bottom: 1px solid $accent-color !default; 143 | $header-navbar-nav-item-ahs-color: $accent-color !default; 144 | $header-navbar-nav-item-ahs-icon-color: $accent-color !default; 145 | 146 | $header-navbar-nav-link-md-font-size: 0.875rem !default; 147 | 148 | $header-navbar-dropdown-item-md-border-radius: 5px !default; 149 | $header-navbar-dropdown-item-md-font-size: 0.875rem !default; 150 | $header-navbar-dropdown-item-md-padding: 0.625rem 1.375rem !default; 151 | $header-navbar-dropdown-item-md-font-weight: 400 !default; 152 | 153 | 154 | // Page Header 155 | $page-title-font-size: 1.625rem !default; 156 | $page-title-sm-font-size: 2rem !default; 157 | $page-title-font-weight: 500 !default; 158 | $page-title-line-height: 1 !default; 159 | $page-title-margin: 0 !default; 160 | $page-title-padding: 0 !default; 161 | 162 | $page-subtitle-letter-spacing: 0.125rem !default; 163 | $page-subtitle-color: $reagent-gray !default; 164 | $page-subtitle-font-size: 0.625rem !default; 165 | $page-subtitle-font-size-sm: 0.8125rem !default; 166 | $page-subtitle-font-weight-sm: 400 !default; 167 | 168 | 169 | // Main footer 170 | $main-footer-height: $main-navbar-height !default; 171 | $main-footer-copyright-color: $reagent-gray !default; 172 | 173 | 174 | // Main sidebar 175 | $dropdown-icon-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMDAwMDAwIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTcuNDEgNy44NEwxMiAxMi40Mmw0LjU5LTQuNThMMTggOS4yNWwtNiA2LTYtNnoiLz4gICAgPHBhdGggZD0iTTAtLjc1aDI0djI0SDB6IiBmaWxsPSJub25lIi8+PC9zdmc+); 176 | $dropdown-icon-width: 0.875rem; 177 | $dropdown-icon-height: 0.5625rem; 178 | $dropdown-icon-background-position: center center; 179 | $dropdown-icon-transition: transform $transition-duration ease-in-out; 180 | 181 | $main-sidebar-height: calc(100vh) !default; 182 | $main-sidebar-zindex: 1070 !default; 183 | $main-sidebar-background: $white !default; 184 | $main-sidebar-will-change: transform !default; 185 | $main-sidebar-transition: transform 200ms ease-in-out !default; 186 | 187 | $main-sidebar-toggle-font-size: 1.25rem !default; 188 | $main-sidebar-toggle-padding: 1.25rem !default; 189 | $main-sidebar-toggle-border-left: 1px solid $border-color !default; 190 | 191 | $main-sidebar-nav-wrapper-height: calc(100vh - 3.75rem - 1px) !default; 192 | $main-sidebar-nav-border-bottom: 1px solid $border-color !default; 193 | 194 | $main-sidebar-nav-link-active-background-color: #FBFBFB !default; 195 | $main-sidebar-nav-link-active-color: $accent-color !default; 196 | $main-sidebar-nav-link-active-box-shadow: inset 0.1875rem 0 0 $accent-color !default; 197 | $main-sidebar-nav-link-active-icon-color: $accent-color !default; 198 | 199 | $main-sidebar-nav-link-border: 1px solid $border-color !default; 200 | $main-sidebar-nav-link-font-weight: 400 !default; 201 | $main-sidebar-nav-link-font-size: 0.85rem !default; 202 | $main-sidebar-nav-link-padding-x: 1.5625rem !default; 203 | $main-sidebar-nav-link-padding-y: 0.9375rem !default; 204 | $main-sidebar-nav-link-color: $fiord-blue !default; 205 | $main-sidebar-nav-link-font-family: $font-family-system-first !default; 206 | $main-sidebar-nav-link-will-change: background-color, box-shadow, color !default; 207 | $main-sidebar-nav-link-transition: box-shadow 200ms ease, 208 | color 200ms ease, 209 | background-color 200ms ease !default; 210 | 211 | $main-sidebar-nav-link-icon-transition: color 200ms ease !default; 212 | $main-sidebar-nav-link-icon-margin-right: 0.375rem !default; 213 | $main-sidebar-nav-link-icon-color: $icon-color !default; 214 | $main-sidebar-nav-link-icon-will-change: color !default; 215 | 216 | $main-sidebar-dropdown-menu-box-shadow: inset 0 -0.1875rem 0.1875rem rgba($fiord-blue, .08) !default; 217 | 218 | $main-sidebar-dropdown-item-background-color-active: $main-sidebar-nav-link-active-background-color !default; 219 | $main-sidebar-dropdown-item-background-hover: none !default; 220 | $main-sidebar-dropdown-item-padding-x: 1.75rem !default; 221 | $main-sidebar-dropdown-item-padding-y: 0.75rem !default; 222 | $main-sidebar-dropdown-item-border: 1px solid lighten($border-color, 5) !default; 223 | $main-sidebar-dropdown-item-last-border: 1px solid $border-color !default; 224 | $main-sidebar-dropdown-item-color: $fiord-blue !default; 225 | $main-sidebar-dropdown-item-active-color: $accent-color !default; 226 | 227 | $main-sidebar-nav-no-borders-nav-link-border-bottom: 0 !default; 228 | $main-sidebar-nav-no-borders-dropdown-menu-box-shadow: inset 0 0 0.4375rem rgba($fiord-blue, .2) !default; 229 | $main-sidebar-nav-no-borders-dropdown-item-first-border-top: $main-sidebar-dropdown-item-last-border !default; 230 | 231 | $main-sidebar-dropdown-item-font-size: 0.8125rem !default; 232 | $main-sidebar-dropdown-item-font-weight: 400 !default; 233 | $main-sidebar-dropdown-item-font-weight-retina: 300 !default; 234 | 235 | 236 | // Components -> Card Post 237 | $card-post-padding-x: 1.5625rem !default; 238 | $card-post-padding-y: 1.5625rem !default; 239 | $card-post-padding: $card-post-padding-y $card-post-padding-x !default; 240 | 241 | $card-post-image-min-height: 10.3125rem !default; 242 | 243 | $card-post-author-avatar-width: 2.8125rem !default; // 45px 244 | $card-post-author-avatar-height: 2.8125rem !default; // 45px 245 | $card-post-author-avatar-small-width: 2.1875rem !default; // 35px 246 | $card-post-author-avatar-small-height: 2.1875rem !default; // 35px 247 | $card-post-author-avatar-box-shadow: 0 0 0 0.125rem $white, 0 0.1875rem 0.4375rem rgba($blueish-grey, 0.5) !default; 248 | 249 | 250 | // Components -> Card Post -> Variation 1 251 | $card-post-v1-author-transform: translateY(50%) !default; 252 | $card-post-v1-author-margin-left: 1.5625rem !default; // 25px 253 | $card-post-v1-category-top: 0.9375rem !default; // 15px 254 | $card-post-v1-category-right: 0.9375rem !default; // 15px 255 | $card-post-v1-body-padding-top: 2.1875rem !default; // 35px 256 | 257 | $card-post-aside-v1-body-padding: $card-post-padding !default; 258 | $card-post-aside-v1-author-left: 0.9375rem !default; // 15px 259 | $card-post-aside-v1-author-bottom: 0.9375rem !default; // 15px 260 | $card-post-aside-v1-category-top: 0.9375rem !default; // 15px 261 | $card-post-aside-v1-category-left: 0.9375rem !default; // 15px 262 | 263 | 264 | // Components -> Sliders 265 | // Core Shards UI sliders adjustments. 266 | $slider-accent-background: $accent-color !default; 267 | $slider-pips-font-size: 0.625rem !default; // 10px 268 | $slider-tooltip-font-size: 0.6875rem !default; // 11px 269 | $slider-tooltip-padding: 0.1875rem 0.5rem !default; // 3,8px 270 | $slider-horizontal-tooltip-bottom: 1.625rem !default; // 26px 271 | $slider-horizontal-handle-left: -0.625rem !default; // -10px 272 | $slider-horizontal-handle-top: -0.5rem !default; // -8px 273 | $slider-handle-width: 1.1875rem !default; // 19px 274 | $slider-handle-height: 1.1875rem !default; // 19px 275 | 276 | 277 | // 278 | // Statistics Blocks and Charts Styles 279 | // 280 | 281 | 282 | // Small stats block 283 | // Used in: Blog overview page templates. 284 | $small-stats-min-height: 8.7rem !default; 285 | 286 | $small-stats-value-font-family: $font-family-roboto-first !default; 287 | $small-stats-value-font-size: 1.5rem !default; 288 | $small-stats-value-font-weight: 500 !default; 289 | $small-stats-value-color: $fiord-blue !default; 290 | 291 | $small-stats-label-font-size: 0.625rem !default; 292 | $small-stats-label-color: $reagent-gray !default; 293 | $small-stats-label-letter-spacing: 0.0625rem !default; 294 | 295 | $small-stats-percentage-font-size: 0.75rem !default; 296 | $small-stats-percentage-padding-left: 0.9375rem !default; 297 | 298 | // Small Stats -- 1 299 | $small-stats-1-data-max-width: 100% !default; 300 | $small-stats-1-percentage-margin: 0 auto !default; 301 | $small-stats-1-value-font-size: 2.0625rem !default; // 33px 302 | $small-stats-1-label-font-size: 0.75rem !default; // 12px 303 | $small-stats-1-percentage-font-size: 0.75rem !default; // 12px 304 | $small-stats-1-chart-opacity: 0.5 !default; 305 | 306 | 307 | // Quick Post Form 308 | // Used in: Blog Overview 309 | $qp-form-display: flex !default; 310 | $qp-form-flex-flow: column !default; 311 | $qp-form-flex: 1 !default; 312 | 313 | $qp-form-textarea-min-height: 100px !default; 314 | 315 | 316 | // Blog Comments Component 317 | // Used in: Blog Overview 318 | $bc-avatar-img-width: 3.125rem !default; // 50px 319 | $bc-avatar-img-height: 3.125rem !default; // 50px 320 | $bc-avatar-img-border-radius: 0.25rem !default; // 4px 321 | 322 | $bc-item-border-bottom: 1px solid $border-color !default; 323 | 324 | $bc-actions-font-size: 95% !default; 325 | $bc-actions-button-group-padding: 0.25rem 0.5625rem !default; 326 | 327 | 328 | // Error(s) templates 329 | $error-tpl-height: calc(100vh - #{$main-navbar-height}) !default; 330 | 331 | $error-tpl-content-padding: 0 0.9375rem !default; // 0,15px 332 | 333 | $error-tpl-content-heading-color: $mischka !default; 334 | $error-tpl-content-heading-font-weight: 700 !default; 335 | $error-tpl-content-heading-font-size: 3.75rem !default; // 60px 336 | $error-tpl-content-heading-margin-bottom: 1.5625rem !default; // 25px 337 | 338 | $error-tpl-content-subheading-font-weight: 500 !default; 339 | $error-tpl-content-subheading-font-size: 2.1875rem !default; // 35px 340 | $error-tpl-content-subheading-margin-bottom: 0.625rem !default; // 10px 341 | 342 | $error-tpl-content-paragraph-color: $reagent-gray !default; 343 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/accent-variations/danger.scss: -------------------------------------------------------------------------------- 1 | // Using 'Danger' as the default accent color. 2 | $accent-color: #c4183c; 3 | 4 | @import '../shards-dashboards'; 5 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/accent-variations/info.scss: -------------------------------------------------------------------------------- 1 | // Using 'Info' as the default accent color. 2 | $accent-color: #00b8d8; 3 | 4 | @import '../shards-dashboards'; 5 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/accent-variations/secondary.scss: -------------------------------------------------------------------------------- 1 | // Using 'Secondary' as the default accent color. 2 | $accent-color: #5A6169; 3 | 4 | @import '../shards-dashboards'; 5 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/accent-variations/success.scss: -------------------------------------------------------------------------------- 1 | // Using 'Success' as the default accent color. 2 | $accent-color: #17c671; 3 | 4 | @import '../shards-dashboards'; 5 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/accent-variations/warning.scss: -------------------------------------------------------------------------------- 1 | // Using 'Warning' as the default accent color. 2 | $accent-color: #ffb400; 3 | 4 | @import '../shards-dashboards'; 5 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/blocks/_main-content.scss: -------------------------------------------------------------------------------- 1 | // Main content adjustments 2 | 3 | .main-content > .main-content-container.container-fluid { 4 | min-height: calc(100vh - #{$main-navbar-height + $main-footer-height}); 5 | } 6 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/blocks/_main-footer.scss: -------------------------------------------------------------------------------- 1 | // Main footer 2 | 3 | .main-footer { 4 | height: $main-footer-height; 5 | 6 | .copyright { 7 | color: $main-footer-copyright-color; 8 | } 9 | 10 | @include media-breakpoint-down(sm) { 11 | display: block !important; 12 | height: auto; 13 | 14 | .nav { 15 | width: 100%; 16 | display: block; 17 | border-bottom: 1px solid $border-color; 18 | padding-bottom: $spacer / 2; 19 | } 20 | 21 | .copyright { 22 | display: inline-block; 23 | width: 100%; 24 | padding: 1rem; 25 | text-align: center; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/blocks/_main-navbar.scss: -------------------------------------------------------------------------------- 1 | // Main navbar adjustments 2 | 3 | .main-navbar .navbar { 4 | height: $main-navbar-height; 5 | 6 | > * { 7 | display: flex; 8 | } 9 | 10 | .nav-link { 11 | min-width: $main-navbar-nav-link-min-width; 12 | } 13 | 14 | // Notifications 15 | .notifications { 16 | position: relative; 17 | 18 | @include media-breakpoint-down(sm) { 19 | position: static; 20 | 21 | .dropdown-menu { 22 | min-width: 100% !important; 23 | border-left: none; 24 | } 25 | } 26 | 27 | .badge { 28 | position: absolute; 29 | padding: $notifications-badge-padding-y $notifications-badge-padding-x; 30 | font-size: $notifications-badge-font-size; 31 | left: 50%; 32 | top: 50%; 33 | } 34 | 35 | .dropdown-menu { 36 | padding: 0; 37 | min-width: $notifications-dropdown-min-width; 38 | border-right: 0; 39 | left: auto; 40 | 41 | // Adjust the dropdown menu on smaller screens. 42 | @include media-breakpoint-down(sm) { 43 | left: 0; 44 | right: 0; 45 | } 46 | 47 | .dropdown-item { 48 | white-space: normal; 49 | display: flex; 50 | flex-flow: row; 51 | padding-top: $notifications-dropdown-item-padding-top; 52 | padding-bottom: $notifications-dropdown-item-padding-bottom; 53 | border-bottom: $notifications-dropdown-item-border-bottom; 54 | 55 | &:last-child { 56 | border-bottom: 0; 57 | } 58 | } 59 | 60 | .notification { 61 | &__icon-wrapper { 62 | display: flex; 63 | padding: 0 5px; 64 | } 65 | 66 | &__icon { 67 | background-color: $notifications-icon-background-color; 68 | box-shadow: $notifications-icon-box-shadow; 69 | width: $notifications-icon-width; 70 | height: $notifications-icon-height; 71 | line-height: 0; 72 | display: block; 73 | text-align: center; 74 | margin: auto; 75 | border-radius: 50%; 76 | 77 | i { 78 | color: $notifications-icon-color; 79 | line-height: $notifications-icon-line-height; 80 | font-size: $notifications-icon-font-size; 81 | margin: 0; 82 | } 83 | } 84 | 85 | &__content { 86 | padding: $notification-content-padding; 87 | 88 | p { 89 | margin: 0; 90 | line-height: 1.5; 91 | font-size: $notification-content-paragraph-font-size; 92 | } 93 | } 94 | 95 | &__category { 96 | font-size: $notification-category-font-size; 97 | color: $notification-category-color; 98 | letter-spacing: $notification-category-letter-spacing; 99 | display: inline-block; 100 | text-transform: uppercase; 101 | margin-bottom: 5px; 102 | font-weight: 500; 103 | } 104 | 105 | // All notifications link. 106 | &__all { 107 | display: block; 108 | font-weight: 500; 109 | font-size: 11px; 110 | border-bottom-left-radius: $border-radius; 111 | border-bottom-right-radius: $border-radius; 112 | } 113 | } 114 | } 115 | } 116 | 117 | // User avatar 118 | .user-avatar { 119 | max-width: $user-avatar-max-width; 120 | } 121 | 122 | // Navbar 123 | .navbar-nav .dropdown-menu { 124 | position: absolute; 125 | right: 0; 126 | width: 100%; 127 | border-top-left-radius: 0; 128 | border-top-right-radius: 0; 129 | border-top: none; 130 | } 131 | 132 | .nav-link-icon i { 133 | line-height: $main-navbar-nav-link-icon-line-height; 134 | } 135 | } 136 | 137 | // Main navbar shadow. 138 | .main-content > .main-navbar, 139 | .main-content .header-navbar { 140 | box-shadow: $main-navbar-box-shadow; 141 | } 142 | 143 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/blocks/_main-sidebar.scss: -------------------------------------------------------------------------------- 1 | // Main sidebar 2 | 3 | .main-sidebar { 4 | top: 0; 5 | position: fixed; 6 | height: $main-sidebar-height; 7 | background: $main-sidebar-background; 8 | z-index: $main-sidebar-zindex; 9 | will-change: $main-sidebar-will-change; 10 | transition: $main-sidebar-transition; 11 | box-shadow: $side-shadow; 12 | 13 | @include media-breakpoint-down(sm) { 14 | transform: translateX(-100%); 15 | box-shadow: none; 16 | } 17 | 18 | // Opened state 19 | &.open { 20 | transform: translateX(0); 21 | box-shadow: $side-shadow; 22 | } 23 | 24 | // Toggle sidebar 25 | .toggle-sidebar { 26 | position: absolute; 27 | right: 0; 28 | height: 100%; 29 | padding: $main-sidebar-toggle-padding; 30 | font-size: $main-sidebar-toggle-font-size; 31 | border-left: $main-sidebar-toggle-border-left; 32 | 33 | &:hover { 34 | cursor: pointer; 35 | } 36 | } 37 | 38 | // Sidebar navbar brand 39 | .navbar-brand { 40 | overflow: hidden; 41 | height: $main-navbar-height; 42 | font-size: $main-navbar-brand-font-size; 43 | 44 | @include media-breakpoint-down(md) { 45 | font-size: 90%; 46 | } 47 | } 48 | 49 | .nav-wrapper { 50 | overflow-y: auto; 51 | overflow-x: hidden; 52 | height: $main-sidebar-nav-wrapper-height; 53 | } 54 | 55 | // Nav 56 | .nav { 57 | .nav-item, 58 | .nav-link { 59 | white-space: nowrap; 60 | min-width: 100%; 61 | max-width: 100%; 62 | overflow: hidden; 63 | text-overflow: ellipsis; 64 | font-family: $main-sidebar-nav-link-font-family; 65 | will-change: $main-sidebar-nav-link-will-change; 66 | transition: $main-sidebar-nav-link-transition; 67 | font-size: $main-sidebar-nav-link-font-size; 68 | } 69 | 70 | .nav-item { 71 | .nav-link { 72 | border-bottom: $main-sidebar-nav-link-border; 73 | font-weight: $main-sidebar-nav-link-font-weight; 74 | color: $main-sidebar-nav-link-color; 75 | padding: $main-sidebar-nav-link-padding-y $main-sidebar-nav-link-padding-x; 76 | 77 | i { 78 | min-width: 1.25rem; 79 | font-size: 90%; 80 | text-align: center; 81 | vertical-align: middle; 82 | will-change: $main-sidebar-nav-link-icon-will-change; 83 | color: $main-sidebar-nav-link-icon-color; 84 | transition: $main-sidebar-nav-link-icon-transition; 85 | margin-right: $main-sidebar-nav-link-icon-margin-right; 86 | } 87 | 88 | i.material-icons { 89 | font-size: 1.125rem; 90 | top: -1px; 91 | } 92 | } 93 | 94 | &.active, .nav-link.active, 95 | &:hover, .nav-link:hover { 96 | box-shadow: $main-sidebar-nav-link-active-box-shadow; 97 | background-color: $main-sidebar-nav-link-active-background-color; 98 | color: $main-sidebar-nav-link-active-color; 99 | 100 | i { 101 | color: $main-sidebar-nav-link-active-icon-color; 102 | } 103 | } 104 | } 105 | 106 | // Nav Item -- No borders 107 | &--no-borders { 108 | .nav-item .nav-link { 109 | border-bottom: $main-sidebar-nav-no-borders-nav-link-border-bottom; 110 | } 111 | 112 | .dropdown-menu { 113 | box-shadow: $main-sidebar-nav-no-borders-dropdown-menu-box-shadow; 114 | 115 | .dropdown-item:first-child { 116 | border-top: $main-sidebar-nav-no-borders-dropdown-item-first-border-top; 117 | } 118 | } 119 | } 120 | } 121 | 122 | // Dropdown menu 123 | .dropdown-menu { 124 | position: static !important; 125 | transform: translate(0) !important; 126 | box-shadow: none; 127 | border-radius: 0; 128 | width: 100%; 129 | border: none; 130 | padding: 0; 131 | box-shadow: $main-sidebar-dropdown-menu-box-shadow; 132 | 133 | .dropdown-item { 134 | padding: $main-sidebar-dropdown-item-padding-y $main-sidebar-dropdown-item-padding-x ; 135 | border-bottom: $main-sidebar-dropdown-item-border; 136 | color: $main-sidebar-dropdown-item-color; 137 | font-size: $main-sidebar-dropdown-item-font-size; 138 | font-weight: $main-sidebar-dropdown-item-font-weight; 139 | 140 | @media (-webkit-min-device-pixel-ratio: 1.5), 141 | (min-resolution: 144dpi) { 142 | font-weight: $main-sidebar-dropdown-item-font-weight-retina; 143 | } 144 | 145 | &:hover, 146 | &.active { 147 | color: $main-sidebar-dropdown-item-active-color; 148 | } 149 | 150 | &:hover { 151 | background: $main-sidebar-dropdown-item-background-hover; 152 | } 153 | 154 | &.active { 155 | background-color: $main-sidebar-dropdown-item-background-color-active; 156 | } 157 | 158 | &:last-of-type { 159 | border-bottom: $main-sidebar-dropdown-item-last-border; 160 | } 161 | } 162 | 163 | .dropdown-divider { 164 | margin: 0; 165 | } 166 | } 167 | 168 | // Dropdown toggle 169 | .dropdown-toggle { 170 | position: relative; 171 | 172 | &::after { 173 | background-image: $dropdown-icon-image; 174 | background-position: $dropdown-icon-background-position; 175 | width: $dropdown-icon-width; 176 | height: $dropdown-icon-height; 177 | transition: $dropdown-icon-transition; 178 | border: none; 179 | position: absolute; 180 | top: 50%; 181 | right: 0.625rem; 182 | transform: translateY(-50%); 183 | opacity: .1; 184 | will-change: transform; 185 | } 186 | } 187 | 188 | .dropdown.show { 189 | .dropdown-toggle::after { 190 | transform: translateY(-50%) rotateZ(180deg); 191 | } 192 | } 193 | 194 | &__search { 195 | @include media-breakpoint-down(sm) { 196 | box-sizing: border-box; 197 | border-right: 0 !important; 198 | padding: 0.625rem 0; 199 | border-bottom: 1px solid $border-color; 200 | 201 | .input-group { 202 | margin: 0 !important; 203 | } 204 | } 205 | } 206 | } 207 | 208 | 209 | // 210 | // Common styles for both main navbar and 211 | // main sidebar search elements. 212 | // 213 | 214 | .main-navbar__search, 215 | .main-sidebar__search { 216 | .input-group-prepend { 217 | .input-group-text { 218 | font-size: 0.6875rem; 219 | padding: 0.75rem 1.0625rem; 220 | } 221 | } 222 | 223 | input.form-control { 224 | border: none; 225 | font-size: 0.8125rem; 226 | border-radius: 0; 227 | 228 | @include hover-focus { 229 | box-shadow: none; 230 | } 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/blocks/_page-header.scss: -------------------------------------------------------------------------------- 1 | // Page headers 2 | // 3 | // Used across the UI kit to emphasize each page by using a title 4 | // and optional description. 5 | 6 | .page-header { 7 | .page-title { 8 | font-size: $page-title-font-size; 9 | font-weight: $page-title-font-weight; 10 | line-height: $page-title-line-height; 11 | margin: $page-title-margin; 12 | padding: $page-title-padding; 13 | 14 | @include media-breakpoint-down(sm) { 15 | font-size: $page-title-sm-font-size; 16 | } 17 | } 18 | 19 | .page-subtitle { 20 | letter-spacing: $page-subtitle-letter-spacing; 21 | color: $page-subtitle-color; 22 | font-size: $page-subtitle-font-size; 23 | 24 | @include media-breakpoint-down(sm) { 25 | font-size: $page-subtitle-font-size-sm; 26 | font-weight: $page-subtitle-font-weight-sm; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/components/_card-post.scss: -------------------------------------------------------------------------------- 1 | // Content Post Component 2 | // Used in templates: Components > Blog Posts 3 | 4 | // Blog Post Cards 5 | .card-post { 6 | 7 | // Adjust the card post inner elements' paddings. 8 | .card-body { 9 | padding: $card-post-padding; 10 | } 11 | 12 | .card-footer, 13 | .card-header { 14 | padding-left: $card-post-padding-x; 15 | padding-right: $card-post-padding-x; 16 | } 17 | 18 | // Card Post :: Image 19 | &__image { 20 | position: relative; 21 | min-height: $card-post-image-min-height; 22 | border-top-left-radius: $card-border-radius; 23 | border-top-right-radius: $card-border-radius; 24 | background-size: cover; 25 | background-position: center; 26 | background-repeat: no-repeat; 27 | } 28 | 29 | // Card Post :: Author :: Avatar 30 | &__author-avatar { 31 | width: $card-post-author-avatar-width; 32 | height: $card-post-author-avatar-height; 33 | box-shadow: $card-post-author-avatar-box-shadow; 34 | display: block; 35 | background-position: center; 36 | background-size: cover; 37 | border-radius: 50%; 38 | text-indent: -9999px; 39 | 40 | // Author Avatar -- Small Modifier 41 | &--small { 42 | width: $card-post-author-avatar-small-width; 43 | height: $card-post-author-avatar-small-height; 44 | } 45 | } 46 | 47 | // Card Post :: Author :: Name 48 | &__author-name { 49 | font-weight: 500; 50 | } 51 | 52 | // Card Post -- Aside Modifier 53 | &--aside { 54 | display: flex; 55 | flex-flow: row; 56 | 57 | .card-post__image { 58 | border-top-right-radius: 0; 59 | border-top-left-radius: $card-border-radius; 60 | border-bottom-left-radius: $card-border-radius; 61 | min-width: 180px; 62 | } 63 | } 64 | 65 | // 66 | // Variations 67 | // 68 | 69 | // Variation 1 70 | &--1 { 71 | .card-post__author, 72 | .card-post__category { 73 | position: absolute; 74 | } 75 | 76 | .card-post__author { 77 | transform: $card-post-v1-author-transform; 78 | margin-left: $card-post-v1-author-margin-left; 79 | position: absolute; 80 | bottom: 0; 81 | } 82 | 83 | .card-post__category { 84 | top: $card-post-v1-category-top; 85 | right: $card-post-v1-category-right; 86 | position: absolute; 87 | text-transform: uppercase; 88 | } 89 | 90 | .card-body { 91 | padding-top: $card-post-v1-body-padding-top; 92 | } 93 | 94 | // Card Post Aside Adjustments 95 | &.card-post--aside { 96 | .card-body { 97 | padding: $card-post-aside-v1-body-padding; 98 | } 99 | 100 | .card-post__author { 101 | left: $card-post-aside-v1-author-left; 102 | bottom: $card-post-aside-v1-author-bottom; 103 | transform: none; 104 | margin: 0; 105 | } 106 | 107 | .card-post__category { 108 | right: initial; 109 | top: $card-post-aside-v1-category-top; 110 | left: $card-post-aside-v1-category-left; 111 | } 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/components/_error.scss: -------------------------------------------------------------------------------- 1 | // Error component 2 | // Used in: Error templates. 3 | 4 | .error { 5 | height: $error-tpl-height; 6 | display: flex; 7 | 8 | &__content { 9 | padding: $error-tpl-content-padding; 10 | display: flex; 11 | flex-flow: column; 12 | margin: auto; 13 | align-items: center; 14 | text-align: center; 15 | 16 | h2 { 17 | color: $error-tpl-content-heading-color; 18 | font-weight: $error-tpl-content-heading-font-weight; 19 | font-size: $error-tpl-content-heading-font-size; 20 | margin-bottom: $error-tpl-content-heading-margin-bottom; 21 | } 22 | 23 | h3 { 24 | font-weight: $error-tpl-content-subheading-font-weight; 25 | font-size: $error-tpl-content-subheading-font-size; 26 | margin-bottom: $error-tpl-content-subheading-margin-bottom; 27 | } 28 | 29 | p { 30 | color: $error-tpl-content-paragraph-color; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/plugins/_quill.scss: -------------------------------------------------------------------------------- 1 | // Quill Adjustments 2 | 3 | // Container 4 | // Note: Using html for specificity here 5 | html { 6 | .ql-container, 7 | .ql-toolbar { 8 | &.ql-snow { 9 | border-color: $border-color; 10 | } 11 | } 12 | 13 | .ql-container { 14 | border-bottom-left-radius: $btn-border-radius; 15 | border-bottom-right-radius: $btn-border-radius; 16 | } 17 | 18 | .ql-editor strong, 19 | .ql-editor b { 20 | font-weight: 600; 21 | } 22 | 23 | .ql-toolbar { 24 | border-top-left-radius: $btn-border-radius; 25 | border-top-right-radius: $btn-border-radius; 26 | color: $headings-color !important; 27 | 28 | .ql-fill, 29 | .ql-stroke.ql-fill { 30 | fill: $reagent-gray; 31 | } 32 | 33 | .ql-stroke { 34 | stroke: $reagent-gray; 35 | } 36 | 37 | button:hover, 38 | button:active, 39 | button:focus { 40 | .ql-fill, 41 | .ql-stroke.ql-fill { 42 | fill: $accent-color !important; 43 | } 44 | 45 | .ql-stroke { 46 | stroke: $accent-color !important; 47 | } 48 | } 49 | 50 | .ql-picker { 51 | .ql-picker-item:hover { 52 | color: $accent-color !important; 53 | } 54 | 55 | .ql-picker-options { 56 | padding: 6px 20px; 57 | border: 0 !important; 58 | box-shadow: $card-box-shadow; 59 | border-radius: $border-radius; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/shards-dashboards.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Shards Dashboard Lite UI Kit v1.1.0 3 | * Project URL: https://designrevision.com/downloads/shards-dashboard-lite 4 | * Based on: Shards UI Kit v2.1.0 (https://designrevision.com/downloads/shards) 5 | * Based on: Bootstrap v4.1.3 (https://getbootstrap.com) 6 | * Copyright 2017-* DesignRevision (https://designrevision.com) 7 | * Copyright 2017-* Catalin Vasile (contact@catalin.me) 8 | * License: MIT 9 | */ 10 | 11 | // Shards variables overrides. 12 | @import "overrides"; 13 | 14 | // Base Shards UI Kit 15 | @import "../../node_modules/shards-ui/src/scss/shards"; 16 | 17 | /* Shards Dashboards Lite Styles */ 18 | 19 | // Core 20 | @import "variables"; 21 | 22 | // Components 23 | @import "reboot"; 24 | @import "buttons"; 25 | @import "button-group"; 26 | @import "navbar"; 27 | @import "badge"; 28 | @import "alert"; 29 | @import "input-group"; 30 | @import "custom-forms"; 31 | @import "custom-sliders"; 32 | @import "images"; 33 | @import "icons"; 34 | @import "dropdown"; 35 | @import "card"; 36 | @import "utilities"; 37 | 38 | // Blocks 39 | @import "blocks/main-navbar"; 40 | @import "blocks/main-sidebar"; 41 | @import "blocks/main-content"; 42 | @import "blocks/main-footer"; 43 | @import "blocks/page-header"; 44 | 45 | // Templates 46 | @import "templates/common"; // Required common styles for all pages. 47 | @import "templates/blog-overview"; 48 | @import "templates/blog-add-new-post"; 49 | 50 | // Plugins 51 | @import "plugins/quill"; 52 | 53 | // Components 54 | @import "components/card-post"; 55 | @import "components/error"; 56 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/templates/_blog-add-new-post.scss: -------------------------------------------------------------------------------- 1 | // Blog Add New Post Template 2 | 3 | // Add New Post Form 4 | .add-new-post { 5 | &__editor { 6 | min-height: 400px; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/templates/_blog-overview.scss: -------------------------------------------------------------------------------- 1 | // Blog Overview Page Template 2 | 3 | // The `Quick Draft` component. 4 | .quick-post-form { 5 | display: $qp-form-display; 6 | flex-flow: $qp-form-flex-flow; 7 | flex: $qp-form-flex; 8 | 9 | // Select second form group el (which contains the textarea). 10 | .form-group:nth-child(2) { 11 | display: flex; 12 | flex: 1; 13 | } 14 | 15 | textarea { 16 | resize: none; 17 | min-height: $qp-form-textarea-min-height; 18 | } 19 | } 20 | 21 | // Blog comments component. 22 | .blog-comments { 23 | &__avatar img { 24 | width: $bc-avatar-img-width; 25 | height: $bc-avatar-img-height; 26 | border-radius: $bc-avatar-img-border-radius; 27 | } 28 | 29 | &__item { 30 | padding: 0; 31 | border-bottom: $bc-item-border-bottom; 32 | 33 | &:last-child { 34 | border: 0; 35 | } 36 | } 37 | 38 | &__actions { 39 | font-size: $bc-actions-font-size; 40 | 41 | .btn-group button { 42 | padding: $bc-actions-button-group-padding; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/templates/_common.scss: -------------------------------------------------------------------------------- 1 | // Common styles for blocks used across all templates. 2 | 3 | // Small stats 4 | // Used in all templates. 5 | 6 | // Default styles for the small stats. 7 | .stats-small { 8 | min-height: $small-stats-min-height; 9 | overflow: hidden !important; 10 | 11 | canvas { 12 | position: absolute; 13 | bottom: 0; 14 | } 15 | 16 | &__data { 17 | flex: 1; 18 | display: flex; 19 | justify-content: center; 20 | flex-flow: column; 21 | max-width: 50%; 22 | z-index: 1; 23 | } 24 | 25 | &__label { 26 | font-size: $small-stats-label-font-size; 27 | letter-spacing: $small-stats-label-letter-spacing; 28 | color: $small-stats-label-color; 29 | } 30 | 31 | &__value { 32 | font-family: $small-stats-value-font-family; 33 | font-size: $small-stats-value-font-size; 34 | font-weight: $small-stats-value-font-weight; 35 | } 36 | 37 | &__percentage { 38 | position: relative; 39 | display: table; 40 | margin-left: auto; 41 | padding-left: $small-stats-percentage-padding-left; 42 | 43 | &--increase, 44 | &--decrease { 45 | font-size: $small-stats-percentage-font-size; 46 | 47 | &::before { 48 | content: ""; 49 | width: 0.75rem; 50 | height: 0.375rem; 51 | position: absolute; 52 | left: 0; 53 | top: 50%; 54 | transform: translateY(-50%); 55 | background-position: center center; 56 | background-repeat: no-repeat; 57 | } 58 | } 59 | 60 | &--increase { 61 | color: theme-color('success'); 62 | &::before { 63 | background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMTdjNjcxIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gPHBhdGggZD0iTTcgMTRsNS01IDUgNXoiLz4gPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPiA8L3N2Zz4=); 64 | } 65 | } 66 | 67 | &--decrease { 68 | color: theme-color('danger'); 69 | &::before { 70 | background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjYzQxODNjIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTcgMTBsNSA1IDUtNXoiLz4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjwvc3ZnPg==); 71 | } 72 | } 73 | } 74 | 75 | // Stats Small - Alternate 1 76 | // Follow the same structure, but with the content centered. 77 | &--1 { 78 | .stats-small { 79 | &__data { 80 | max-width: $small-stats-1-data-max-width; 81 | } 82 | 83 | &__percentage { 84 | margin: $small-stats-1-percentage-margin; 85 | } 86 | 87 | &__value { 88 | font-size: $small-stats-1-value-font-size; 89 | } 90 | 91 | &__label { 92 | font-size: $small-stats-1-label-font-size; 93 | } 94 | 95 | &__percentage { 96 | font-size: $small-stats-1-percentage-font-size; 97 | } 98 | } 99 | 100 | canvas { 101 | opacity: $small-stats-1-chart-opacity; 102 | } 103 | } 104 | } 105 | 106 | // Adjust the small stats cards in case they're used inside card groups. 107 | .card-group .stats-small { 108 | position: relative; 109 | overflow: hidden; 110 | } 111 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/utilities/_borders.scss: -------------------------------------------------------------------------------- 1 | // Borders adjustments 2 | .border { border: 1px solid $border-color !important; } 3 | .border-top { border-top: 1px solid $border-color !important; } 4 | .border-right { border-right: 1px solid $border-color !important; } 5 | .border-bottom { border-bottom: 1px solid $border-color !important; } 6 | .border-left { border-left: 1px solid $border-color !important; } 7 | 8 | // Border radius 9 | 10 | .rounded { 11 | border-radius: 5px !important; 12 | } 13 | 14 | .rounded-top { 15 | border-top-left-radius: 5px !important; 16 | border-top-right-radius: 5px !important; 17 | } 18 | 19 | .rounded-right { 20 | border-top-right-radius: 5px !important; 21 | border-bottom-right-radius: 5px !important; 22 | } 23 | 24 | .rounded-bottom { 25 | border-bottom-right-radius: 5px !important; 26 | border-bottom-left-radius: 5px !important; 27 | } 28 | 29 | .rounded-left { 30 | border-top-left-radius: 5px !important; 31 | border-bottom-left-radius: 5px !important; 32 | } 33 | 34 | // Accent color border variation 35 | .border-accent { 36 | border-color: $accent-color !important; 37 | } 38 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/utilities/_general.scss: -------------------------------------------------------------------------------- 1 | // General utilities 2 | 3 | // Overflow helpers 4 | .overflow { 5 | &-hidden { overflow: hidden; } 6 | &-visible { overflow: visible; } 7 | &-scroll { overflow: scroll; } 8 | &-auto { overflow: auto; } 9 | } 10 | 11 | // Remove shadows 12 | .no-shadow { 13 | box-shadow: none !important; 14 | } 15 | -------------------------------------------------------------------------------- /bot_manager_web/statics/styles/scss/utilities/_text.scss: -------------------------------------------------------------------------------- 1 | // Text utilities adjustments 2 | 3 | // Create text color variants for the new grays 4 | @each $color, $value in $new-grays { 5 | @include text-emphasis-variant(".text-#{$color}", $value); 6 | } 7 | 8 | // Create text color variants for the accent color 9 | @include text-emphasis-variant(".text-accent", $accent-color); 10 | 11 | // Light text adjustments 12 | .text-light { 13 | color: $text-light-color !important; 14 | } 15 | 16 | // Semibold text 17 | .text-semibold { 18 | font-weight: $text-semibold-font-weight; 19 | } 20 | -------------------------------------------------------------------------------- /bot_manager_web/templates/group_list.html: -------------------------------------------------------------------------------- 1 | {% extends "share/article.html" %} 2 | {% block article %} 3 |
4 | {% for item in items %} 5 |
7 |
8 | {{ item['group_id'] }} 9 | {{ item['group_name'] }} 10 |
11 |
12 | {% endfor %} 13 |
14 | {% endblock %} -------------------------------------------------------------------------------- /bot_manager_web/templates/group_services.html: -------------------------------------------------------------------------------- 1 | {% extends "share/article.html" %} 2 | {% block article %} 3 |
4 | {% for key in conf[group_id] %} 5 |
6 |
7 | {{ key }} 8 | 11 |
12 |
13 | {% endfor %} 14 |
15 |
16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | {% endblock %} 24 | {% block afterload %} 25 | 91 | {% endblock %} -------------------------------------------------------------------------------- /bot_manager_web/templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "share/bare_base.html" %} 2 | {% block imports %} 3 | 4 | 5 | {% endblock %} 6 | {% block main %} 7 |
8 | {% include "share/main_header.html" %} 9 |
10 |
11 |
12 |
13 |
登录
14 |
15 |
    16 |
  • 17 |
    18 |
    19 |
    20 |
    21 | 29 |
    30 | 31 | 36 |
    37 | 38 |
    39 |
    40 | 41 | 43 |
    44 |
    45 |
    46 |
    47 |
  • 48 |
49 |
50 |
51 |
52 |
53 | {% endblock %} 54 | {% block afterload %} 55 | 80 | {% endblock %} -------------------------------------------------------------------------------- /bot_manager_web/templates/manage.html: -------------------------------------------------------------------------------- 1 | {% extends "share/article.html" %} 2 | {% block article %} 3 |
4 |
5 | 6 |
7 |
8 |
9 |
10 | 按服务管理 11 |
12 |
13 | 按群管理 14 |
15 |
16 | {% endblock %} -------------------------------------------------------------------------------- /bot_manager_web/templates/service_groups.html: -------------------------------------------------------------------------------- 1 | {% extends "share/article.html" %} 2 | {% block article %} 3 |
4 | {% for group in groups %} 5 | 6 |
7 |
8 | {{ group["group_id"] }} 9 | {{ group["group_name"] }} 10 | 11 |
12 |
13 | {% endfor %} 14 |
15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 |
23 |
24 | {% endblock %} 25 | {% block afterload %} 26 | 27 | 92 | {% endblock %} -------------------------------------------------------------------------------- /bot_manager_web/templates/service_list.html: -------------------------------------------------------------------------------- 1 | {% extends "share/article.html" %} 2 | {% block article %} 3 |
4 | {% for item in items %} 5 |
6 | {{ item }} 8 |
9 | {% endfor %} 10 |
11 | {% endblock %} -------------------------------------------------------------------------------- /bot_manager_web/templates/share/after_load.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /bot_manager_web/templates/share/article.html: -------------------------------------------------------------------------------- 1 | {% extends "share/base.html" %} 2 | {% block main %} 3 |
4 | {% include "share/main_header.html" %} 5 |
6 |
7 |
8 |
9 |
{% if article_title %}{{ article_title }}{% endif %}
10 |
11 |
    12 |
  • 13 |
    14 |
    15 | {% block article %} 16 |
    17 | 19 |
    20 | {% endblock %} 21 |
    22 |
    23 |
  • 24 |
25 |
26 |
27 |
28 |
29 | {% endblock %} -------------------------------------------------------------------------------- /bot_manager_web/templates/share/bare_base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% if title %}{{ title }}{% else %}bot{% endif %} 5 | {% include "share/imports.html" %} 6 | {% block imports %}{% endblock %} 7 | 8 | 9 |
10 |
11 |
12 |
13 |
14 | {% block main %} 15 | {% endblock %} 16 | {% include "share/main_footer.html" %} 17 |
18 |
19 |
20 | {% block afterload %}{% endblock %} 21 | 22 | -------------------------------------------------------------------------------- /bot_manager_web/templates/share/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% if title %}{{ title }}{% else %}bot{% endif %} 5 | {% include "share/imports.html" %} 6 | {% block imports %}{% endblock %} 7 | 8 | 9 |
10 |
11 |
12 |
13 | {% include "share/main_slide_bar.html" %} 14 |
15 | {% include "share/main_nav_bar.html" %} 16 | {% block main %} 17 | {% endblock %} 18 | {% include "share/main_footer.html" %} 19 |
20 |
21 |
22 | {% block afterload %}{% endblock %} 23 | 24 | -------------------------------------------------------------------------------- /bot_manager_web/templates/share/error.html: -------------------------------------------------------------------------------- 1 | {% extends "share/base.html" %} 2 | {% block main %} 3 |
4 |
5 |

{% if statusCode %}{{ statusCode }}{% else %}500{% endif %}

6 |

Something went wrong!

7 |

{{ msg }}

8 | 9 |
10 |
11 | {% endblock %} -------------------------------------------------------------------------------- /bot_manager_web/templates/share/form.html: -------------------------------------------------------------------------------- 1 | {% extends "share/base.html" %} 2 | {% block imports %} 3 | 4 | 5 | {% endblock %} 6 | {% block main %} 7 |
8 | {% include "share/main_header.html" %} 9 |
10 |
11 |
12 |
13 |
{{ msg }}
14 |
15 |
    16 |
  • 17 |
    18 |
    19 | {% block form %} 20 |
    21 | {% csrf_token %} 22 | 24 |
    25 | {% endblock %} 26 |
    27 |
    28 |
  • 29 |
30 |
31 |
32 |
33 |
34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /bot_manager_web/templates/share/imports.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /bot_manager_web/templates/share/main_footer.html: -------------------------------------------------------------------------------- 1 |
2 | 7 | {% if icp_content %} 8 | Copyright © 2018 9 | {{ icp_content }} 10 | 11 | {% endif %} 12 |
-------------------------------------------------------------------------------- /bot_manager_web/templates/share/main_header.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bot_manager_web/templates/share/main_nav_bar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bot_manager_web/templates/share/main_slide_bar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bot_manager_web/templates/share/table.html: -------------------------------------------------------------------------------- 1 | {% extends "share/base.html" %} 2 | {% block main %} 3 |
4 | {% include "share/main_header.html" %} 5 |
6 |
7 |
8 |
9 |
{{ msg }}
10 |
11 |
12 | {% block table %} 13 | {% endblock %} 14 |
15 |
16 |
17 |
18 |
19 | {% endblock %} -------------------------------------------------------------------------------- /bot_manager_web/view.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import nonebot 4 | from datetime import timedelta 5 | from hoshino import Service 6 | from quart import request, session, redirect, Blueprint 7 | from .http_handler import render_template, get_random_str 8 | import hoshino 9 | 10 | # 访问bot manager web的密码。公网服务没有身份验证是很危险的,密码建议自行修改!!! 11 | PASSWORD = os.environ.get('BOT_MANAGER_WEB_PASSWORD') if os.environ.get('BOT_MANAGER_WEB_PASSWORD') else '987654321' 12 | 13 | switcher = Blueprint('switcher', __name__, static_folder='statics', static_url_path='/statics', url_prefix="/manage") 14 | bot = nonebot.get_bot() 15 | app = bot.server_app 16 | if not app.config.get('SECRET_KEY'): 17 | app.config['SECRET_KEY'] = get_random_str(10) 18 | 19 | 20 | async def get_groups(): 21 | gl = [] 22 | for sid in hoshino.get_self_ids(): 23 | gl_ = await bot.get_group_list(self_id=sid) 24 | for g in gl_: 25 | if g not in gl: 26 | gl.append(g) 27 | 28 | return gl 29 | 30 | 31 | @switcher.before_request 32 | async def _(): 33 | user_ip = request.remote_addr 34 | if session.get('user_ip') == user_ip: 35 | return 36 | if request.path.startswith(switcher.url_prefix): 37 | r_path = request.path[len(switcher.url_prefix):] 38 | if r_path == '/login': 39 | return 40 | if r_path.startswith(switcher.static_url_path): 41 | return 42 | if r_path == '/check': 43 | return 44 | return redirect(switcher.url_prefix + '/login') 45 | 46 | 47 | @switcher.route('/login', methods=['GET', 'POST']) 48 | async def login(): 49 | if request.method == 'GET': 50 | return await render_template('login.html', title='登录', static_url_path=switcher.static_url_path, 51 | url_prefix=switcher.url_prefix) 52 | else: 53 | login_data = await request.form 54 | input_psd = login_data.get('password') 55 | if input_psd == PASSWORD: 56 | user_ip = request.remote_addr 57 | session['user_ip'] = user_ip 58 | session.permanent = True 59 | app.permanent_session_lifetime = timedelta(weeks=2) 60 | return redirect(switcher.url_prefix + '/') 61 | else: 62 | return redirect(switcher.url_prefix + '/login') 63 | 64 | 65 | @switcher.route('/') 66 | async def manage(): 67 | user = {'name': 'name'} 68 | return await render_template('manage.html', title='欢迎', user=user, static_url_path=switcher.static_url_path, 69 | url_prefix=switcher.url_prefix) 70 | 71 | 72 | @switcher.route('/group') 73 | async def group_list(): 74 | user = {'name': 'name'} 75 | groups = await get_groups() 76 | return await render_template('group_list.html', title='按群管理', article_title="按群管理", items=groups, user=user, 77 | static_url_path=switcher.static_url_path, url_prefix=switcher.url_prefix) 78 | 79 | 80 | @switcher.route('/service') 81 | async def service_list(): 82 | user = {'name': 'name'} 83 | svs = Service.get_loaded_services() 84 | sv_names = list(svs) 85 | return await render_template('service_list.html', title='按服务管理', article_title="按服务管理", items=sv_names, user=user, 86 | static_url_path=switcher.static_url_path, url_prefix=switcher.url_prefix) 87 | 88 | 89 | @switcher.route('/group/') 90 | async def show_group_services(gid_str: str): 91 | user = {'name': 'name'} 92 | gid = int(gid_str) 93 | svs = Service.get_loaded_services() 94 | conf = {gid_str: {}} 95 | for key in svs: 96 | conf[gid_str][key] = svs[key].check_enabled(gid) 97 | return await render_template('group_services.html', title=f'群{gid_str}服务一览', article_title=f'群{gid_str}服务一览', 98 | user=user, group_id=gid_str, conf=conf, static_url_path=switcher.static_url_path, 99 | url_prefix=switcher.url_prefix) 100 | 101 | 102 | @switcher.route('/service/') 103 | async def show_service_groups(sv_name: str): 104 | user = {'name': 'name'} 105 | svs = Service.get_loaded_services() 106 | groups = await get_groups() 107 | conf = {} 108 | for group in groups: 109 | gid = group['group_id'] 110 | gid_str = str(gid) 111 | conf[gid_str] = {} 112 | if svs[sv_name].check_enabled(gid): 113 | conf[gid_str][sv_name] = True 114 | else: 115 | conf[gid_str][sv_name] = False 116 | return await render_template('service_groups.html', title=f'服务 {sv_name} ', article_title=sv_name, sv_name=sv_name, 117 | conf=conf, groups=groups, user=user, static_url_path=switcher.static_url_path, 118 | url_prefix=switcher.url_prefix) 119 | 120 | 121 | @switcher.route('/set', methods=['GET', 'POST']) 122 | async def set_group(): 123 | # 接收前端传来的配置数据,数据格式{"":{'serviceA':True,'serviceB':False}} 124 | if request.method == 'POST': 125 | data = await request.get_data() 126 | conf = json.loads(data.decode()) 127 | svs = Service.get_loaded_services() 128 | for k in conf: 129 | gid = int(k) 130 | for sv_name in conf[k]: 131 | if conf[k][sv_name]: 132 | svs[sv_name].set_enable(gid) 133 | svs[sv_name].logger.info(f'启用群 {gid} 服务 {sv_name} ') 134 | else: 135 | svs[sv_name].set_disable(gid) 136 | svs[sv_name].logger.info(f'禁用群 {gid} 服务 {sv_name}') 137 | return 'ok' 138 | --------------------------------------------------------------------------------