diff --git a/README-JP.md b/README-JP.md index 5dab3ac3f..9a63d7ec3 100644 --- a/README-JP.md +++ b/README-JP.md @@ -41,7 +41,7 @@ ## 利用方法 -詳細な利用方法については、[ブログ](https://www.emqx.io/blog/mqtt-x-guideline)または[ユーザーマニュアル](./docs/manual.md)を確認してください。 +詳細な利用方法については、[ブログ](https://qiita.com/emqx_japan/items/1ff6097fdfe273c5e22f)または[ユーザーマニュアル](./docs/manual-jp.md)を確認してください。 1. MQTT Brokerの準備。 diff --git a/assets/emqx_wx.jpeg b/assets/emqx_wx.jpeg new file mode 100644 index 000000000..f1aa87efb Binary files /dev/null and b/assets/emqx_wx.jpeg differ diff --git a/assets/mqttx-preview.png b/assets/mqttx-preview.png index 9ebc9d6dd..5a4f274b9 100644 Binary files a/assets/mqttx-preview.png and b/assets/mqttx-preview.png differ diff --git a/assets/mqttx-script.png b/assets/mqttx-script.png new file mode 100644 index 000000000..1e5cd752f Binary files /dev/null and b/assets/mqttx-script.png differ diff --git a/docs/manual-cn.md b/docs/manual-cn.md index 5cf6b1e7c..c21965fe0 100644 --- a/docs/manual-cn.md +++ b/docs/manual-cn.md @@ -179,6 +179,24 @@ sudo snap install mqttx ![mqttx-advance](../assets/mqttx-advance.png) +### 脚本 + +在 v1.4.2 版本以后,MQTT X 新增了脚本编辑功能,在该功能中,用户可编写自定义脚本(JavaScript)对发送和接收到的 `Payload` 进行自定义转化,配合定时发送功能,可实现一些模拟数据上报的自动化测试功能。 + +> 注意:该功能目前属于测试 Beta 阶段。 + +点击左侧菜单栏中的 `脚本` 按钮,可进入到脚本编辑页面,在该页面中,用户可在最上方的代码编辑器中,编写 JavaScript 代码,全局只包含一个 `execute` API,用户需要编写一个脚本函数,该函数接收一个 `value` 参数,即为 `Payload`, 函数中便可对 `value` 进行自定义修改转化,最后将该函数作为参数传入到 `execute` 中即可执行自定义编写的函数。 + +下方还包含了一个 `输入` 和 `输出` 框,可输入预想输入值,点击右边的 `测试` 按钮,便可在 `输出` 框中查看执行结果,输入的值的格式包含了 `JSON` 和 `Plaintext`,方便用户提前调试自定义编写的脚本功能。完成测试后,可点击最右上角的 `保存` 按钮,输入该脚本的名称后就可对该脚本进行保存。保存完成后就可以到连接页面进行使用了。保存完成的脚本还可进行编辑和删除。 + +在连接页面中,点击右上角的下拉功能菜单,选择 `使用脚本`,在弹出窗中,选择你需要使用的预先保存好的脚本,然后选择应用类型,包含了,发送时,接收时和全部。选择完成后,根据数据类型选择发送或接收的数据格式,正常使用消息的收发,此时如果看到预期效果,便完成了一个完整的脚本使用的功能。如果用户需要取消脚本,可点击顶部状态栏中的红色的 `停止脚本` 按钮,便可停止使用脚本。 + +该功能具有一定的扩展性和灵活性,需用户配合实际需求来进行使用。 + +![mqttx-script](../assets/mqttx-script.png) + +脚本使用实例可在 [/docs/script-example](https://github.com/emqx/MQTTX/tree/master/docs/script-example) 文件夹中查看,目前提供了两个内置脚本,时间戳转化和温湿度数据模拟。如果在您的使用中有更好的,更实用的脚本也可以提交您的代码到这里,方便让更多的人使用到。 + ### 其它 1. 连接操作 @@ -263,4 +281,8 @@ Linux: `vue-cli-service electron:build --linux` | 方式 | 内容 | | ---- | ---- | | QQ 群(EMQ X 官方群3)| 937041105 | -| EMQ X 官方公众号 | MQTTX Logo | +| EMQ X 官方公众号 | WeChat QR code | +| EMQ X 微信群(扫码添加后邀请入群)| EMQ X Wechat | +| 微博 | [@emqtt](https://weibo.com/emqtt) | +| Twitter | [@emqtt](https://twitter.com/emqtt/) | +| Slack | [EMQ X](https://slack-invite.emqx.io/) | diff --git a/docs/manual.md b/docs/manual.md index ba34d4ce4..609a5d6a2 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -179,6 +179,24 @@ In the settings page, you can choose to click the data backup and data recovery ![mqttx-advance](../assets/mqttx-advance.png) +### Script + +After the v1.4.2 version, MQTT X has added a script editing function. In this function, users can write custom scripts (JavaScript) to perform custom conversions on sent and received `Payload`. With the timing sending function, realize the automated test function for the simulation data report. + +> Note: This feature is test feature in the beta stage + +Click the `script` button in the menu bar on the left to enter the script editing page. In this page, users can write JavaScript code in the code editor at the top. There is only one `execute` API globally, and the user needs write a script function that receives a `value` parameter, which is `Payload`, and the function can be customized to modify the `value`, and finally the function can be executed by passing it as a parameter to the `execute` custom-written functions. + +There is also an `input` and `output` box below. You can enter the expected input value. Click the `test` button on the right to view the execution result in the `output` box. The format of the input value includes `JSON` With `Plaintext`, it is convenient for users to debug custom-written script functions in advance. After completing the test, you can click the `Save` button in the upper right corner and enter the name of the script to save the script. After saving, you can go to the connection page for use. The saved script can also be edited and deleted. + +In the connection page, click the drop-down menu in the upper right corner, select `Use script`, in the pop-up window, select the pre-saved script you need to use, and then select the script to be applied, including: Published, Received, and All. After the selection is completed, select the data format to be sent or received according to the data type, and use the message sending and receiving normally. At this time, if the expected effect is seen, a script function is completed. If the user needs to cancel the script, you can click the red `Stop script` button in the top status bar to stop using the script. + +This function is scalable and flexible, and requires users to cooperate with actual needs to use it. + +![mqttx-script](../assets/mqttx-script.png) + +The script usage examples can be viewed in the [/docs/script-example](https://github.com/emqx/MQTTX/tree/master/docs/script-example) folder. Currently, two built-in scripts are provided, timestamp conversion and temperature and humidity data simulation. If you have a better and more practical script in your use, you can submit your code here, so that more people can use it. + ### Others 1. Connection operation diff --git a/docs/script-example/tempAndHum.js b/docs/script-example/tempAndHum.js new file mode 100644 index 000000000..2f845c581 --- /dev/null +++ b/docs/script-example/tempAndHum.js @@ -0,0 +1,21 @@ +/** + * Simulated temperature and humidity reporting + * @return Return a simulated temperature and humidity JSON data - { "temperature": 23, "humidity": 40 } + * @param value, MQTT Payload - {} + */ + +function random(min, max) { + return Math.round(Math.random() * (max - min)) + min +} + +function handlePayload(value) { + let _value = value + if (typeof value === 'string') { + _value = JSON.parse(value) + } + _value.temperature = random(10, 30) + _value.humidity = random(20, 40) + return JSON.stringify(_value, null, 2) +} + +execute(handlePayload) diff --git a/docs/script-example/timestamp.js b/docs/script-example/timestamp.js new file mode 100644 index 000000000..c3508ecdb --- /dev/null +++ b/docs/script-example/timestamp.js @@ -0,0 +1,18 @@ +/** + * Convert timestamp to normal time. + * @return Return the UTC time - { "time": "2020-12-17 14:18:07" } + * @param value, MQTT Payload - { "time": 1608185887 } + */ + +function handleTimestamp(value) { + let _value = value + if (typeof value === 'string') { + _value = JSON.parse(value) + } + // East Eight District needs an additional 8 hours + const date = new Date(_value.time * 1000 + 8 * 3600 * 1000) + _value.time = date.toJSON().substr(0, 19).replace('T', ' ') + return JSON.stringify(_value, null, 2) +} + +execute(handleTimestamp) diff --git a/package.json b/package.json index d89aa1452..7e38d8971 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "MQTTX", - "version": "1.4.1", + "version": "1.4.2", "description": "MQTT desktop client", "author": "EMQ X Team", "scripts": { @@ -39,11 +39,10 @@ "vuex": "^3.0.1", "vuex-class": "^0.3.2", "xlsx": "^0.16.8", - "xml-js": "^1.6.11" + "xml-js": "^1.6.11", + "vm2": "latest" }, "devDependencies": { - "@fullhuman/postcss-purgecss": "^2.1.0", - "@fullhuman/vue-cli-plugin-purgecss": "~2.2.0", "@types/chai": "^4.1.0", "@types/chart.js": "^2.9.28", "@types/fs-extra": "^8.0.0", @@ -76,11 +75,6 @@ "vue-cli-plugin-electron-builder": "^1.4.6", "vue-template-compiler": "^2.6.12" }, - "postcss": { - "plugins": { - "autoprefixer": {} - } - }, "browserslist": [ "> 1%", "last 2 versions" diff --git a/postcss.config.js b/postcss.config.js index ba414c28a..90d9fffcb 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,15 +1,5 @@ -const IN_PRODUCTION = process.env.NODE_ENV === 'production' - module.exports = { - plugins: [ - IN_PRODUCTION && require('@fullhuman/postcss-purgecss')({ - content: [`./public/**/*.html`, `./src/**/*.vue`, `./src/**/*.scss`], - defaultExtractor (content) { - const contentWithoutStyleBlocks = content.replace(//gi, '') - return contentWithoutStyleBlocks.match(/[A-Za-z0-9-_/:]*[A-Za-z0-9-_/]+/g) || [] - }, - whitelist: [], - whitelistPatterns: [ /-(leave|enter|appear)(|-(to|from|active))$/, /^(?!(|.*?:)cursor-move).+-move$/, /^router-link(|-exact)-active$/, /data-v-.*/ ], - }) - ], + plugins: { + autoprefixer: {}, + }, } diff --git a/src/api/script.ts b/src/api/script.ts new file mode 100644 index 000000000..d91fb5180 --- /dev/null +++ b/src/api/script.ts @@ -0,0 +1,22 @@ +import db from '@/database/index' +import { ScriptModel } from '@/views/script/types' + +export const createScript = (data: ScriptModel): ScriptModel => { + return db.insert('scripts', data) +} + +export const loadScripts = (): ScriptModel[] | [] => { + return db.get('scripts') +} + +export const deleteScript = (id: string): ScriptModel => { + return db.remove('scripts', id) +} + +export const updateScript = (id: string, data: ScriptModel): ScriptModel => { + return db.update('scripts', id, data) +} + +export const loadScript = (id: string): ScriptModel => { + return db.find('scripts', id) +} diff --git a/src/assets/font/iconfont.css b/src/assets/font/iconfont.css index 21cad3611..9b363f55d 100644 --- a/src/assets/font/iconfont.css +++ b/src/assets/font/iconfont.css @@ -1,10 +1,10 @@ @font-face {font-family: "iconfont"; - src: url('iconfont.eot?t=1578016411003'); /* IE9 */ - src: url('iconfont.eot?t=1578016411003#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), - url('iconfont.woff?t=1578016411003') format('woff'), - url('iconfont.ttf?t=1578016411003') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ - url('iconfont.svg?t=1578016411003#iconfont') format('svg'); /* iOS 4.1- */ + src: url('iconfont.eot?t=1606729533448'); /* IE9 */ + src: url('iconfont.eot?t=1606729533448#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), + url('iconfont.woff?t=1606729533448') format('woff'), + url('iconfont.ttf?t=1606729533448') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ + url('iconfont.svg?t=1606729533448#iconfont') format('svg'); /* iOS 4.1- */ } .iconfont { @@ -15,107 +15,143 @@ -moz-osx-font-smoothing: grayscale; } -.icon-reddit:before { - content: "\e7e4"; +.icon-coding:before { + content: "\e617"; +} + +.icon-download:before { + content: "\e657"; +} + +.icon-microsoft:before { + content: "\e632"; +} + +.icon-ubuntu:before { + content: "\e71d"; +} + +.icon-mac:before { + content: "\e698"; +} + +.icon-linux:before { + content: "\e77d"; +} + +.icon-windows:before { + content: "\ea06"; +} + +.icon-arrow:before { + content: "\e651"; +} + +.icon-reddit1:before { + content: "\e621"; } .icon-qq:before { content: "\e615"; } +.icon-reddit:before { + content: "\e7e4"; +} + .icon-weibo:before { content: "\e73a"; } -.icon-slack:before { - content: "\e641"; +.icon-we-chat:before { + content: "\e70e"; } -.icon-zhedie:before { - content: "\e600"; +.icon-ttww:before { + content: "\e6c7"; } -.icon-we-chat:before { - content: "\e70e"; +.icon-slack:before { + content: "\e641"; } -.icon-edit:before { - content: "\e626"; +.icon-liebiao:before { + content: "\e64b"; } -.icon-brokers:before { - content: "\e625"; +.icon-fenzu:before { + content: "\e64c"; } -.icon-settings:before { - content: "\e627"; +.icon-connection:before { + content: "\e64d"; } -.icon-connections:before { - content: "\e628"; +.icon-new:before { + content: "\e64e"; } -.icon-website:before { - content: "\e629"; +.icon-about:before { + content: "\e64f"; } -.icon-github:before { - content: "\e62a"; +.icon-site:before { + content: "\e650"; } -.icon-disconnect:before { - content: "\e62b"; +.icon-zhedie:before { + content: "\e600"; } -.icon-delete:before { - content: "\e62c"; +.icon-plus:before { + content: "\e630"; } -.icon-clear:before { - content: "\e62d"; +.icon-search:before { + content: "\e631"; } -.icon-client:before { - content: "\e62e"; +.icon-edit:before { + content: "\e626"; } .icon-send:before { content: "\e62f"; } -.icon-search:before { - content: "\e631"; +.icon-disconnect:before { + content: "\e62b"; } -.icon-plus:before { - content: "\e630"; +.icon-delete:before { + content: "\e62c"; } -.icon-liebiao:before { - content: "\e64b"; +.icon-clear:before { + content: "\e62d"; } -.icon-fenzu:before { - content: "\e64c"; +.icon-client:before { + content: "\e62e"; } -.icon-connection:before { - content: "\e64d"; +.icon-website:before { + content: "\e629"; } -.icon-new:before { - content: "\e64e"; +.icon-github:before { + content: "\e62a"; } -.icon-about:before { - content: "\e64f"; +.icon-connections:before { + content: "\e628"; } -.icon-site:before { - content: "\e650"; +.icon-brokers:before { + content: "\e625"; } -.icon-ttww:before { - content: "\e6c7"; +.icon-settings:before { + content: "\e627"; } diff --git a/src/assets/font/iconfont.eot b/src/assets/font/iconfont.eot index 43451669e..cbc7a9b1a 100644 Binary files a/src/assets/font/iconfont.eot and b/src/assets/font/iconfont.eot differ diff --git a/src/assets/font/iconfont.js b/src/assets/font/iconfont.js index fd15a3d2a..8efc18073 100644 --- a/src/assets/font/iconfont.js +++ b/src/assets/font/iconfont.js @@ -1 +1,59 @@ -!function(s){var l,e='',c=(l=document.getElementsByTagName("script"))[l.length-1].getAttribute("data-injectcss");if(c&&!s.__iconfont__svg__cssinject__){s.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}!function(l){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(l,0);else{var c=function(){document.removeEventListener("DOMContentLoaded",c,!1),l()};document.addEventListener("DOMContentLoaded",c,!1)}else document.attachEvent&&(h=l,i=s.document,o=!1,(e=function(){try{i.documentElement.doScroll("left")}catch(l){return void setTimeout(e,50)}t()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,t())});function t(){o||(o=!0,h())}var h,i,o,e}(function(){var l,c,t,h,i,o;(l=document.createElement("div")).innerHTML=e,e=null,(c=l.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",t=c,(h=document.body).firstChild?(i=t,(o=h.firstChild).parentNode.insertBefore(i,o)):h.appendChild(t))})}(window); \ No newline at end of file +!(function (c) { + var l, + a, + t, + h, + i, + o, + s = + '', + e = (e = document.getElementsByTagName('script'))[e.length - 1].getAttribute('data-injectcss') + if (e && !c.__iconfont__svg__cssinject__) { + c.__iconfont__svg__cssinject__ = !0 + try { + document.write( + '', + ) + } catch (c) { + console && console.log(c) + } + } + function d() { + i || ((i = !0), t()) + } + ;(l = function () { + var c, l, a, t + ;((t = document.createElement('div')).innerHTML = s), + (s = null), + (a = t.getElementsByTagName('svg')[0]) && + (a.setAttribute('aria-hidden', 'true'), + (a.style.position = 'absolute'), + (a.style.width = 0), + (a.style.height = 0), + (a.style.overflow = 'hidden'), + (c = a), + (l = document.body).firstChild ? ((t = c), (a = l.firstChild).parentNode.insertBefore(t, a)) : l.appendChild(c)) + }), + document.addEventListener + ? ~['complete', 'loaded', 'interactive'].indexOf(document.readyState) + ? setTimeout(l, 0) + : ((a = function () { + document.removeEventListener('DOMContentLoaded', a, !1), l() + }), + document.addEventListener('DOMContentLoaded', a, !1)) + : document.attachEvent && + ((t = l), + (h = c.document), + (i = !1), + (o = function () { + try { + h.documentElement.doScroll('left') + } catch (c) { + return void setTimeout(o, 50) + } + d() + })(), + (h.onreadystatechange = function () { + 'complete' == h.readyState && ((h.onreadystatechange = null), d()) + })) +})(window) diff --git a/src/assets/font/iconfont.json b/src/assets/font/iconfont.json index c19453306..720b18534 100644 --- a/src/assets/font/iconfont.json +++ b/src/assets/font/iconfont.json @@ -6,11 +6,67 @@ "description": "", "glyphs": [ { - "icon_id": "1663480", + "icon_id": "11348940", + "name": "coding", + "font_class": "coding", + "unicode": "e617", + "unicode_decimal": 58903 + }, + { + "icon_id": "16144037", + "name": "download", + "font_class": "download", + "unicode": "e657", + "unicode_decimal": 58967 + }, + { + "icon_id": "6720830", + "name": "microsoft", + "font_class": "microsoft", + "unicode": "e632", + "unicode_decimal": 58930 + }, + { + "icon_id": "3994864", + "name": "ubuntu", + "font_class": "ubuntu", + "unicode": "e71d", + "unicode_decimal": 59165 + }, + { + "icon_id": "11111717", + "name": "mac", + "font_class": "mac", + "unicode": "e698", + "unicode_decimal": 59032 + }, + { + "icon_id": "11305187", + "name": "linux", + "font_class": "linux", + "unicode": "e77d", + "unicode_decimal": 59261 + }, + { + "icon_id": "11983514", + "name": "windows", + "font_class": "windows", + "unicode": "ea06", + "unicode_decimal": 59910 + }, + { + "icon_id": "13091253", + "name": "arrow", + "font_class": "arrow", + "unicode": "e651", + "unicode_decimal": 58961 + }, + { + "icon_id": "8262530", "name": "reddit", - "font_class": "reddit", - "unicode": "e7e4", - "unicode_decimal": 59364 + "font_class": "reddit1", + "unicode": "e621", + "unicode_decimal": 58913 }, { "icon_id": "1878149", @@ -19,6 +75,13 @@ "unicode": "e615", "unicode_decimal": 58901 }, + { + "icon_id": "1663480", + "name": "reddit", + "font_class": "reddit", + "unicode": "e7e4", + "unicode_decimal": 59364 + }, { "icon_id": "1937032", "name": "weibo", @@ -26,6 +89,20 @@ "unicode": "e73a", "unicode_decimal": 59194 }, + { + "icon_id": "9277879", + "name": "we-chat", + "font_class": "we-chat", + "unicode": "e70e", + "unicode_decimal": 59150 + }, + { + "icon_id": "12313365", + "name": "twitter", + "font_class": "ttww", + "unicode": "e6c7", + "unicode_decimal": 59079 + }, { "icon_id": "3876355", "name": "slack", @@ -33,6 +110,48 @@ "unicode": "e641", "unicode_decimal": 58945 }, + { + "icon_id": "12198496", + "name": "列表", + "font_class": "liebiao", + "unicode": "e64b", + "unicode_decimal": 58955 + }, + { + "icon_id": "12198497", + "name": "分组", + "font_class": "fenzu", + "unicode": "e64c", + "unicode_decimal": 58956 + }, + { + "icon_id": "12198498", + "name": "connection", + "font_class": "connection", + "unicode": "e64d", + "unicode_decimal": 58957 + }, + { + "icon_id": "12198499", + "name": "new", + "font_class": "new", + "unicode": "e64e", + "unicode_decimal": 58958 + }, + { + "icon_id": "12198500", + "name": "about", + "font_class": "about", + "unicode": "e64f", + "unicode_decimal": 58959 + }, + { + "icon_id": "12198501", + "name": "site", + "font_class": "site", + "unicode": "e650", + "unicode_decimal": 58960 + }, { "icon_id": "9047144", "name": "折叠", @@ -41,11 +160,18 @@ "unicode_decimal": 58880 }, { - "icon_id": "9277879", - "name": "we-chat", - "font_class": "we-chat", - "unicode": "e70e", - "unicode_decimal": 59150 + "icon_id": "9770925", + "name": "icon-plus", + "font_class": "plus", + "unicode": "e630", + "unicode_decimal": 58928 + }, + { + "icon_id": "9617831", + "name": "search", + "font_class": "search", + "unicode": "e631", + "unicode_decimal": 58929 }, { "icon_id": "9408416", @@ -55,39 +181,11 @@ "unicode_decimal": 58918 }, { - "icon_id": "9504241", - "name": "brokers", - "font_class": "brokers", - "unicode": "e625", - "unicode_decimal": 58917 - }, - { - "icon_id": "9504243", - "name": "settings", - "font_class": "settings", - "unicode": "e627", - "unicode_decimal": 58919 - }, - { - "icon_id": "9507416", - "name": "connections", - "font_class": "connections", - "unicode": "e628", - "unicode_decimal": 58920 - }, - { - "icon_id": "9552002", - "name": "website", - "font_class": "website", - "unicode": "e629", - "unicode_decimal": 58921 - }, - { - "icon_id": "9552003", - "name": "github", - "font_class": "github", - "unicode": "e62a", - "unicode_decimal": 58922 + "icon_id": "9559673", + "name": "send", + "font_class": "send", + "unicode": "e62f", + "unicode_decimal": 58927 }, { "icon_id": "9558958", @@ -118,74 +216,39 @@ "unicode_decimal": 58926 }, { - "icon_id": "9559673", - "name": "send", - "font_class": "send", - "unicode": "e62f", - "unicode_decimal": 58927 - }, - { - "icon_id": "9617831", - "name": "search", - "font_class": "search", - "unicode": "e631", - "unicode_decimal": 58929 - }, - { - "icon_id": "9770925", - "name": "icon-plus", - "font_class": "plus", - "unicode": "e630", - "unicode_decimal": 58928 - }, - { - "icon_id": "12198496", - "name": "列表", - "font_class": "liebiao", - "unicode": "e64b", - "unicode_decimal": 58955 - }, - { - "icon_id": "12198497", - "name": "分组", - "font_class": "fenzu", - "unicode": "e64c", - "unicode_decimal": 58956 - }, - { - "icon_id": "12198498", - "name": "connection", - "font_class": "connection", - "unicode": "e64d", - "unicode_decimal": 58957 + "icon_id": "9552002", + "name": "website", + "font_class": "website", + "unicode": "e629", + "unicode_decimal": 58921 }, { - "icon_id": "12198499", - "name": "new", - "font_class": "new", - "unicode": "e64e", - "unicode_decimal": 58958 + "icon_id": "9552003", + "name": "github", + "font_class": "github", + "unicode": "e62a", + "unicode_decimal": 58922 }, { - "icon_id": "12198500", - "name": "about", - "font_class": "about", - "unicode": "e64f", - "unicode_decimal": 58959 + "icon_id": "9507416", + "name": "connections", + "font_class": "connections", + "unicode": "e628", + "unicode_decimal": 58920 }, { - "icon_id": "12198501", - "name": "site", - "font_class": "site", - "unicode": "e650", - "unicode_decimal": 58960 + "icon_id": "9504241", + "name": "brokers", + "font_class": "brokers", + "unicode": "e625", + "unicode_decimal": 58917 }, { - "icon_id": "12313365", - "name": "twitter", - "font_class": "ttww", - "unicode": "e6c7", - "unicode_decimal": 59079 + "icon_id": "9504243", + "name": "settings", + "font_class": "settings", + "unicode": "e627", + "unicode_decimal": 58919 } ] } diff --git a/src/assets/font/iconfont.svg b/src/assets/font/iconfont.svg index 512053e4d..7c3b500b1 100644 --- a/src/assets/font/iconfont.svg +++ b/src/assets/font/iconfont.svg @@ -20,82 +20,109 @@ Created by iconfont /> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/src/assets/font/iconfont.ttf b/src/assets/font/iconfont.ttf index 4c4157469..8272af0dd 100644 Binary files a/src/assets/font/iconfont.ttf and b/src/assets/font/iconfont.ttf differ diff --git a/src/assets/font/iconfont.woff b/src/assets/font/iconfont.woff index 6df688385..7bb257419 100644 Binary files a/src/assets/font/iconfont.woff and b/src/assets/font/iconfont.woff differ diff --git a/src/assets/font/iconfont.woff2 b/src/assets/font/iconfont.woff2 index 689c7d5ec..0715a64e1 100644 Binary files a/src/assets/font/iconfont.woff2 and b/src/assets/font/iconfont.woff2 differ diff --git a/src/assets/scss/mixins.scss b/src/assets/scss/mixins.scss index f5802add0..9a66db134 100644 --- a/src/assets/scss/mixins.scss +++ b/src/assets/scss/mixins.scss @@ -55,3 +55,18 @@ } } } + +@mixin editor-lang-type { + .lang-type { + width: 100%; + height: 30px; + line-height: 30px; + padding: 0px 12px; + background: var(--color-bg-radio); + border: 1px solid var(--color-border-default); + border-top: none; + text-align: right; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + } +} diff --git a/src/background.ts b/src/background.ts index 9616b5cdb..3ebc9aa00 100644 --- a/src/background.ts +++ b/src/background.ts @@ -60,6 +60,9 @@ function handleIpcMessages() { const { id, receivedMessage } = args[0] updateConnectionMessage(id, { ...receivedMessage }) }) + ipcMain.on('initEditor', (event: Electron.Event, ...args: any[]) => { + event.sender.send('initEditor') + }) } function createWindow() { diff --git a/src/components/Editor.vue b/src/components/Editor.vue index f6e5737d9..40b0f9409 100644 --- a/src/components/Editor.vue +++ b/src/components/Editor.vue @@ -14,6 +14,8 @@ export default class Editor extends Vue { @Prop({ required: true }) public id!: string @Prop({ required: true }) public lang!: string @Prop({ default: 14 }) public fontSize!: number + @Prop({ default: 'off' }) public lineNumbers!: 'off' | 'on' + @Prop({ default: 'none' }) public renderHighlight!: 'none' | 'line' @Prop({ default: 'hidden' }) public scrollbarStatus: 'auto' | 'visible' | 'hidden' | undefined @Prop({ default: false }) public disabled!: boolean @@ -48,15 +50,15 @@ export default class Editor extends Vue { } } - private initEditor(): void | boolean { + public initEditor(): void | boolean { const defaultOptions: monaco.editor.IStandaloneEditorConstructionOptions = { value: this.value, language: this.lang, readOnly: this.disabled, fontSize: this.fontSize, scrollBeyondLastLine: false, - lineNumbers: 'off', - renderLineHighlight: 'none', + lineNumbers: this.lineNumbers, + renderLineHighlight: this.renderHighlight, matchBrackets: 'near', folding: false, theme: this.getTheme(), @@ -94,6 +96,13 @@ export default class Editor extends Vue { this.editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => { this.$emit('enter-event', this.value) }) + // tslint:disable-next-line:no-bitwise + this.editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => { + this.$emit('enter-event', this.value) + }) + this.editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S, () => { + this.$emit('qucik-save', this.value) + }) // Update editor options const model = this.editor.getModel() if (model) { @@ -106,7 +115,7 @@ export default class Editor extends Vue { this.$emit('blur') }) } - private editorLayout() { + public editorLayout() { if (this.editor) { this.editor.layout() } diff --git a/src/components/ExportData.vue b/src/components/ExportData.vue index fad1af56e..0a77c7cde 100644 --- a/src/components/ExportData.vue +++ b/src/components/ExportData.vue @@ -47,7 +47,7 @@ import { loadConnections } from '@/api/connection' import MyDialog from './MyDialog.vue' import { ConnectionModel } from '@/views/connections/types' import XMLConvert from 'xml-js' -const { parse: CSVConvert } = require('json2csv') +import { parse as CSVConvert } from 'json2csv' import ExcelConvert, { WorkBook } from 'xlsx' type ExportFormat = 'JSON' | 'XML' | 'CSV' | 'Excel' diff --git a/src/components/Leftbar.vue b/src/components/Leftbar.vue index 9550e8daa..2577893f7 100644 --- a/src/components/Leftbar.vue +++ b/src/components/Leftbar.vue @@ -17,6 +17,11 @@ +
+ + + +
@@ -56,6 +61,9 @@ export default class Leftbar extends Vue { get isAbout(): boolean { return this.$route.path === '/about' } + get isScript(): boolean { + return this.$route.path === '/script' + } get isNewWindow(): boolean { return this.$route.name === 'newWindow' } diff --git a/src/components/MessageList.vue b/src/components/MessageList.vue index 4769ff514..cbe47ad77 100644 --- a/src/components/MessageList.vue +++ b/src/components/MessageList.vue @@ -1,6 +1,11 @@