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)
- }
- }
- }} />
-
-
+
+
+
+
+
+
+
{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}>
-
+
+
)
@@ -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;