diff --git a/i18n/en_US/global.json b/i18n/en_US/global.json index c8126aa..66798e8 100644 --- a/i18n/en_US/global.json +++ b/i18n/en_US/global.json @@ -1,8 +1,10 @@ { "sidebar": "Access URL", "port": "Port", - "generate": "Generate", + "generate": "Generate URL", "refresh": "Refresh", + "description": "Access links create a link for external access for your application. Before you create an access link, map the application port you want to access to address 0.0.0.0 in the terminal. ", + "help": "View help", "handleDelete": { "header": "Are you sure to delete this port?", "message": "You're trying to delete port {port}", @@ -13,6 +15,8 @@ "createSuccess": "Create success!", "deleteFailed": "Delete failed: {msg}", "deleteSuccess": "Delete success!", + "copySuccess": "Copy success!", + "copyFailed": "Copy failed!", "saveFailed": "Permanent failed: {msg}", "saveSuccess": "Permanent success!", "memberInfo": "Only a diamond member can generate a permanent link" @@ -20,4 +24,4 @@ "neverExpires": "Never Expires", "permanent": "Permanent", "expires": "Expires: " -} \ No newline at end of file +} diff --git a/i18n/zh_CN/global.json b/i18n/zh_CN/global.json index 15258ec..ed06233 100644 --- a/i18n/zh_CN/global.json +++ b/i18n/zh_CN/global.json @@ -1,8 +1,10 @@ { "sidebar": "访问链接", "port": "端口", - "generate": "生成", + "generate": "创建链接", "refresh": "刷新", + "description": "访问链接可为应用程序创建一个供外部访问的链接,创建访问链接前,请在终端(Terminal)中将需要被访问的应用程序端口映射到 0.0.0.0 地址。", + "help": "查看帮助", "handleDelete": { "header": "你确定删除此端口吗", "message": "你正在删除端口 {port}", @@ -13,6 +15,8 @@ "createSuccess": "创建成功!", "deleteFailed": "删除失败: {msg}", "deleteSuccess": "删除成功!", + "copySuccess": "复制成功!", + "copyFailed": "复制失败!", "saveFailed": "永久化失败: {msg}", "saveSuccess": "永久化成功!", "memberInfo": "只有钻石会员才能生成永久链接" @@ -20,4 +24,4 @@ "neverExpires": "永不过期", "permanent": "转为永久", "expires": "过期: " -} \ No newline at end of file +} diff --git a/src/AccessUrl.jsx b/src/AccessUrl.jsx index b091466..d7c2c27 100644 --- a/src/AccessUrl.jsx +++ b/src/AccessUrl.jsx @@ -2,12 +2,13 @@ import React, { Component, PropTypes } from 'react'; var ReactDOM = require('react-dom'); import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import Clipboard from 'lib/clipboard'; import * as AccessUrlActions from './actions'; import cx from 'classnames'; import { global } from './manager'; import QRCode from 'qrcode.react'; -const { notify, NOTIFY_TYPE } = global.sdk.Notify; +const { notify, NOTIFY_TYPE } = global.sdk.Notify; const Modal = global.sdk.Modal; const i18n = global.i18n; @@ -18,13 +19,27 @@ class AccessUrl extends Component { isLoading: true, ticks: 0, showQR: false, + port: 8080, } + this.handlePort = this.handlePort.bind(this); + this.handlePortIncrease = this.handlePortIncrease.bind(this); + this.handlePortDecrease = this.handlePortDecrease.bind(this); + this.handleEnterGenerate = this.handleEnterGenerate.bind(this); + this.handleGenerate = this.handleGenerate.bind(this); } componentWillMount () { this.fetch() } componentDidMount () { - + const clipboard = new Clipboard('.clipboard', { + text: trigger => trigger.parentElement.parentElement.querySelector('.ip-content').getAttribute('href'), + }); + clipboard.on('success', (e) => { + notify({message: `${e.text} ${i18n.get('global.message.copySuccess')}`}); + }); + clipboard.on('error', (e) => { + notify({message: i18n.get('global.message.copyFailed')}); + }); } componentWillUnmount () { if (this.cdInterval) { @@ -32,7 +47,7 @@ class AccessUrl extends Component { this.cdInterval = undefined } } - + render() { const { portList, generateDisabled } = this.props return ( @@ -44,26 +59,26 @@ class AccessUrl extends Component { {i18n`global.sidebar`} -
- {i18n`global.port`} - { this.portInput = input; }} onKeyDown={(e) => { - if (e.keyCode === 13) { - if (!generateDisabled) { - this.handleGenerate(e) - } - } - }} /> - -
+
+
+ {i18n`global.description`} + {i18n`global.help`} +
+
+
+ 0.0.0.0 : + +
+
+
+
+
+ +
+
{portList.length > 0 ? ( portList.map((port) => { @@ -140,9 +155,43 @@ class AccessUrl extends Component { text += sec < 10 ? "0" + sec : "" + sec; return text; } + + handlePort(e) { + let value = e.target.value; + if (value !== '') { + value = Number(value); + if (Number.isNaN(value) || value > 100000) { + return; + } + } + this.setState({port: value}); + } + + handlePortIncrease() { + if (this.state.port < 10000) { + this.setState((prevState) => ({ + port: prevState.port + 1, + })); + } + } + + handlePortDecrease() { + if (this.state.port > 0) { + this.setState((prevState) => ({ + port: prevState.port - 1, + })); + } + } + + handleEnterGenerate(e) { + if (e.keyCode === 13) { + this.handleGenerate(e); + } + } + handleGenerate = (e) => { e.preventDefault() - this.props.actions.createPort({ port: this.portInput.value}).then((res) => { + this.props.actions.createPort({ port: this.state.port}).then((res) => { this.setState({ isLoading: false, ticks: 0 @@ -178,7 +227,7 @@ class AccessUrl extends Component { handleDelete = async (port) => { var confirmed = await Modal.showModal('Confirm', { header: i18n`global.handleDelete.header`, - message: i18n`global.handleDelete.message${port}`, + message: i18n`global.handleDelete.message${{port}}`, okText: i18n`global.handleDelete.okText` }) Modal.dismissModal() @@ -201,7 +250,8 @@ class AccessUrl extends Component { } const PortItem = ({ node, handleOpenQR, handleCloseQR, handleDelete, handlePermanent, ttl }) => { - let ttlDom = '' + const ip = `0.0.0.0:${node.port}`; + let ttlDom = ''; if (ttl === -1) { ttlDom =
{i18n`global.neverExpires`}
} else { @@ -209,23 +259,24 @@ const PortItem = ({ node, handleOpenQR, handleCloseQR, handleDelete, handlePerma - +
} return (
- handleOpenQR(e, node.url)} onMouseLeave={handleCloseQR} /> + handleOpenQR(e, node.url)} onMouseLeave={handleCloseQR}>
- {node.url} + {ip} {ttlDom}
- + +
) @@ -237,11 +288,11 @@ const mapStateToProps = (state) => { generateDisabled, portList = [] } } = state - return ({ + return ({ generateDisabled, portList }); }; export default connect(mapStateToProps, dispatch => ({ actions: bindActionCreators(AccessUrlActions, dispatch) -}))(AccessUrl); \ No newline at end of file +}))(AccessUrl); diff --git a/src/base-theme/styles/accessUrl.styl b/src/base-theme/styles/accessUrl.styl index e6e51de..b438db8 100644 --- a/src/base-theme/styles/accessUrl.styl +++ b/src/base-theme/styles/accessUrl.styl @@ -16,7 +16,7 @@ .panel-heading { height: 28px; line-height: 28px; - background-color: $pane-item-background-color; + background-color: $pane-item-border-color; padding: 0 10px; display: flex; input { @@ -60,24 +60,66 @@ } } .panel-body { + min-width: 280px; position: absolute; top: 28px; bottom: 0; left: 0; right: 0; overflow: auto; + .create-url { + padding-bottom: 20px; + border-bottom: 1px solid $pane-item-background-color; + .url-tip { + padding: 10px; + line-height: 20px; + font-size: 14px; + color: #737373; + } + .url-generate { + display: flex; + .port { + display: flex; + align-items: center; + height: 36px; + padding: 0 5px 0 10px; + margin: 0 10px; + border: 2px solid #404040; + border-radius: 2px; + span { + color: #6e6e6e; + } + input { + width: 70px; + height: 100%; + margin: 0 5px; + border: none; + outline: none; + background-color: transparent; + } + .change { + display: block; + width: 10px; + .fa { + width: 10px; + height: 15px; + line-height: 15px; + cursor: pointer; + } + } + } + } + } } .port-item { padding: 10px; border-bottom: 1px solid $pane-item-background-color; position: relative; display: flex; + align-items: center; .qrcode { - width: 27px; - height: 27px; - font-size: 30px; - line-height: 30px; - margin-right: 6px; + font-size: 46px; + margin-right: 8px; } .port-content { flex-grow: 1; @@ -86,12 +128,14 @@ } .extra { .fa { + margin-right: 10px; cursor: pointer; } } .post-item-info { line-height: 22px; display: flex; + align-items: center; padding-top: 4px; } .post-item-ttl { @@ -101,6 +145,7 @@ line-height: 26px; } .post-item-upgrade { + color: #4377b6; cursor: pointer; .fa { margin-right: 4px; @@ -122,4 +167,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/manager.js b/src/manager.js index 5a1b5e4..ff8ebab 100644 --- a/src/manager.js +++ b/src/manager.js @@ -25,10 +25,8 @@ export default class { key: 'access-url', actions: { onSidebarActive: () => { - console.log('Access URL is active'); }, onSidebarDeactive: () => { - console.log('Access URL is deactive'); }, }, }, extension => extension.app); @@ -38,7 +36,6 @@ export default class { * @param {} */ pluginWillUnmount() { - console.log('plugin will UnMount'); } get component() { return component;