mirror of
https://github.com/openstf/stf
synced 2025-10-05 02:29:26 +02:00
Add upload and installation errors.
This commit is contained in:
parent
7ea5dd2777
commit
2f172c2fda
14 changed files with 165 additions and 69 deletions
4
res/app/components/stf/install/index.js
Normal file
4
res/app/components/stf/install/index.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
module.exports = angular.module('stf.install-service', [
|
||||
require('gettext').name
|
||||
])
|
||||
.filter('installError', require('./install-error-filter'))
|
12
res/app/components/stf/install/install-error-filter.js
Normal file
12
res/app/components/stf/install/install-error-filter.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
// From here: https://github.com/android/platform_frameworks_base/blob/
|
||||
// master/core/java/android/content/pm/PackageManager.java#L371
|
||||
|
||||
module.exports = function installErrorFilter(gettext) {
|
||||
return function (text) {
|
||||
return {
|
||||
INSTALL_FAILED_OLDER_SDK: gettext('New package failed because the ' +
|
||||
'current SDK version is older than that required by the package')
|
||||
// TODO: do the rest
|
||||
}[text] || text
|
||||
}
|
||||
}
|
13
res/app/components/stf/install/install-spec.js
Normal file
13
res/app/components/stf/install/install-spec.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
describe('install', function() {
|
||||
|
||||
beforeEach(angular.mock.module(require('./').name))
|
||||
|
||||
it('should ...', inject(function($filter) {
|
||||
|
||||
var filter = $filter('install')
|
||||
|
||||
expect(filter('input')).toEqual('output')
|
||||
|
||||
}))
|
||||
|
||||
})
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module.exports = function LanguageProvider(AppStateProvider) {
|
||||
var provider = {
|
||||
selectedLanguage: 'en'
|
||||
selectedLanguage: 'ja' // default
|
||||
}
|
||||
|
||||
var a = AppStateProvider.$get()
|
||||
|
|
4
res/app/components/stf/upload/index.js
Normal file
4
res/app/components/stf/upload/index.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
module.exports = angular.module('stf.upload-service', [
|
||||
require('gettext').name
|
||||
])
|
||||
.filter('uploadError', require('./upload-error-filter'))
|
10
res/app/components/stf/upload/upload-error-filter.js
Normal file
10
res/app/components/stf/upload/upload-error-filter.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
module.exports = function uploadErrorFilter(gettext) {
|
||||
return function (text) {
|
||||
return {
|
||||
'fail_invalid_app_file': gettext('Uploaded file is not valid'),
|
||||
'fail_download': gettext('Failed to download file'),
|
||||
'fail_invalid_url': gettext('Cannot access specified URL'),
|
||||
'fail': gettext('Upload failed')
|
||||
}[text] || gettext('Upload unknown error')
|
||||
}
|
||||
}
|
13
res/app/components/stf/upload/upload-spec.js
Normal file
13
res/app/components/stf/upload/upload-spec.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
describe('upload', function() {
|
||||
|
||||
beforeEach(angular.mock.module(require('./').name))
|
||||
|
||||
it('should ...', inject(function($filter) {
|
||||
|
||||
var filter = $filter('upload')
|
||||
|
||||
expect(filter('input')).toEqual('output')
|
||||
|
||||
}))
|
||||
|
||||
})
|
|
@ -6,7 +6,9 @@ module.exports = angular.module('stf.upload', [
|
|||
'angularFileUpload',
|
||||
require('./activities').name,
|
||||
require('stf/settings').name,
|
||||
require('stf/storage').name
|
||||
require('stf/storage').name,
|
||||
require('stf/install').name,
|
||||
require('stf/upload').name
|
||||
])
|
||||
.run(["$templateCache", function ($templateCache) {
|
||||
$templateCache.put('control-panes/dashboard/upload/upload.jade',
|
||||
|
|
|
@ -31,6 +31,7 @@ module.exports = function UploadCtrl(
|
|||
$scope.$apply(function () {
|
||||
$scope.upload = uploadResult
|
||||
})
|
||||
|
||||
if (uploadResult.success) {
|
||||
return $scope.maybeInstall(uploadResult.body)
|
||||
}
|
||||
|
@ -93,7 +94,6 @@ module.exports = function UploadCtrl(
|
|||
$scope.upload = null
|
||||
}
|
||||
else {
|
||||
console.log('Upload error', err)
|
||||
$scope.upload = {
|
||||
progress: 100
|
||||
, lastData: 'fail'
|
||||
|
@ -105,6 +105,7 @@ module.exports = function UploadCtrl(
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
$scope.maybeInstall = function (options) {
|
||||
if ($scope.installEnabled) {
|
||||
return $scope.control.install(options)
|
||||
|
@ -120,6 +121,7 @@ module.exports = function UploadCtrl(
|
|||
installResult.manifest = options.manifest
|
||||
$scope.treeData = installResult.manifest
|
||||
$scope.installation = installResult
|
||||
$scope.installationError = installResult.error
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
input(type='checkbox', ng-model='installEnabled')
|
||||
span(translate) Install
|
||||
|
||||
.widget-content.padded(style='padding: 0; padding-bottom: 15px;')
|
||||
// TODO: remove padding-bottom when drop file is implemented
|
||||
.widget-content.padded()
|
||||
//.widget-content.padded(style='padding: 0; padding-bottom: 15px;')
|
||||
|
||||
//.col-md-10.col-md-offset-1
|
||||
//.input-group.form-inline
|
||||
|
@ -31,24 +31,6 @@
|
|||
//treecontrol.tree-classic(tree-model='treeData', options='treeOptions')
|
||||
span employee: {{node.name}} age {{node.age}}
|
||||
|
||||
pre(ng-if='upload.error') Error: {{ upload.error }}
|
||||
p(translate) Error
|
||||
div(ng-switch='upload.error')
|
||||
strong(ng-switch-when='fail_invalid_app_file')
|
||||
span(translate) Uploaded file is not valid
|
||||
strong(ng-switch-when='fail_download')
|
||||
span(translate) Failed to download file
|
||||
strong(ng-switch-when='fail_invalid_url')
|
||||
span(translate) Cannot access specified URL
|
||||
strong(ng-switch-when='fail')
|
||||
span(translate) Upload failed
|
||||
strong(ng-switch-default)
|
||||
span Error code: {{ upload.error }}
|
||||
|
||||
//.upload-status(ng-if='upload && !upload.settled')
|
||||
progressbar(max='100', value='upload.progress', ng-if='!upload.settled',
|
||||
ng-class='{"active": !upload.settled}').progress-striped
|
||||
|
||||
.upload-status(ng-if='upload || installation')
|
||||
|
||||
accordion(close-others='false').pointer
|
||||
|
@ -96,3 +78,12 @@
|
|||
|
||||
progressbar(max='100', value='taskProgress()', ng-if='!taskFinished()',
|
||||
ng-class='{"active": !taskFinished()}').progress-striped
|
||||
|
||||
|
||||
alert(type='danger', close='upload.error = null', ng-show='upload.error')
|
||||
strong(translate) Error:
|
||||
span {{ upload.error | uploadError | translate }}
|
||||
|
||||
alert(type='danger', close='installationError = undefined', ng-show='installationError')
|
||||
strong(translate) Error:
|
||||
span {{ installationError | installError | translate }} ({{ installationError }})
|
||||
|
|
|
@ -403,3 +403,14 @@ input {
|
|||
.transparent-border {
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
/* Bootstrap close button is misaligned for some reason */
|
||||
.alert-dismissable .close,
|
||||
.alert-dismissible .close {
|
||||
right: auto;
|
||||
}
|
||||
|
||||
/* Reset alert margin */
|
||||
.alert {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
|
|
@ -130,10 +130,6 @@ msgstr "バッテリー温度"
|
|||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/browser/browser.html
|
||||
msgid "Browser"
|
||||
msgstr "ブラウザ"
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/device/device-info-filter/index.js
|
||||
msgid "Busy"
|
||||
msgstr "貸し出し中"
|
||||
|
@ -150,7 +146,7 @@ msgstr "CPU"
|
|||
msgid "Camera"
|
||||
msgstr "カメラ"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/upload/upload.html
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/upload/upload-error-filter.js
|
||||
msgid "Cannot access specified URL"
|
||||
msgstr "指定されたURLはアクセスできません"
|
||||
|
||||
|
@ -305,13 +301,6 @@ msgstr "放電中"
|
|||
msgid "Disconnected"
|
||||
msgstr "切断中"
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/socket/socket-state/socket-state-directive.js
|
||||
msgid ""
|
||||
"Disconnected.<br />Socket connection was lost, try again reloading the page."
|
||||
msgstr ""
|
||||
"接続が切れました。<br />ソケット接続が失われました。もう一度ページを再ロード"
|
||||
"してみてください。"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/info/info.html
|
||||
msgid "Display"
|
||||
msgstr "ディスプレー"
|
||||
|
@ -344,10 +333,6 @@ msgstr "通知を有効にする"
|
|||
msgid "Encrypted"
|
||||
msgstr "暗号化"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/upload/upload.html
|
||||
msgid "Error"
|
||||
msgstr "エラー"
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/control/control-service.js
|
||||
msgid "Error while getting data"
|
||||
msgstr "データ取得中にエラーが発生しました。"
|
||||
|
@ -360,6 +345,10 @@ msgstr "再接続中にエラーが発生しました。"
|
|||
msgid "Error."
|
||||
msgstr "エラー"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/upload/upload.html
|
||||
msgid "Error:"
|
||||
msgstr "エラー:"
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/control-panes/advanced/port-forwarding/port-forwarding-controller.js
|
||||
msgid "Error: Forwarding ports failed."
|
||||
msgstr "エラー:ポートフォワーディングが失敗しました。"
|
||||
|
@ -372,7 +361,7 @@ msgstr "イーサーネット"
|
|||
msgid "FPS"
|
||||
msgstr "FPS"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/upload/upload.html
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/upload/upload-error-filter.js
|
||||
msgid "Failed to download file"
|
||||
msgstr "ファイルのダウンロードが失敗しした。"
|
||||
|
||||
|
@ -599,6 +588,14 @@ msgstr "ブラウジング"
|
|||
msgid "Network"
|
||||
msgstr "ネットワーク"
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/install/install-error-filter.js
|
||||
msgid ""
|
||||
"New package failed because the current SDK version is older than that "
|
||||
"required by the package"
|
||||
msgstr ""
|
||||
"この端末のSDKバージョンがパッケージが必要としているSDKのバージョンより古いた"
|
||||
"め、失敗しました。"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/advanced/input/input.html
|
||||
msgid "Next"
|
||||
msgstr "次"
|
||||
|
@ -631,6 +628,10 @@ msgstr "写真はありません"
|
|||
msgid "No screenshots taken"
|
||||
msgstr "キャプチャはありません"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/automation/device-settings/device-settings.html
|
||||
msgid "Normal Mode"
|
||||
msgstr "通常モード"
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/device/device-info-filter/index.js
|
||||
msgid "Not Charging"
|
||||
msgstr "充電されていない"
|
||||
|
@ -805,22 +806,10 @@ msgstr "正常に再接続しました。"
|
|||
msgid "Record"
|
||||
msgstr "記録する"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/shell/shell.html
|
||||
msgid "Reference"
|
||||
msgstr "参考"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/components/stf/common-ui/refresh-page/refresh-page.html
|
||||
msgid "Refresh"
|
||||
msgstr "更新"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/browser/browser.html
|
||||
msgid "Relaunch"
|
||||
msgstr "再起動"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/browser/browser.html
|
||||
msgid "Relaunch the browser"
|
||||
msgstr "ブラウザを再起動する"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/info/info.html
|
||||
#: /Users/a12907/STF/stf/res/app/device-list/device-column-service.js
|
||||
msgid "Released"
|
||||
|
@ -831,13 +820,11 @@ msgstr "発売日"
|
|||
msgid "Reload"
|
||||
msgstr "再読込"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/advanced/remote-debug/remote-debug.html
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/remote-debug/remote-debug.html
|
||||
msgid "Remote debug"
|
||||
msgstr "リモートデバッグ"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/device-list/device-list.html
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/browser/browser.html
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/navigation/navigation.html
|
||||
msgid "Reset"
|
||||
msgstr "初期化"
|
||||
|
@ -846,7 +833,6 @@ msgstr "初期化"
|
|||
msgid "Reset Settings"
|
||||
msgstr "すべての設定をリセット"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/browser/browser.html
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/navigation/navigation.html
|
||||
msgid "Reset all browser settings"
|
||||
msgstr "ブラウザの設定をリセットする"
|
||||
|
@ -895,17 +881,20 @@ msgstr "JavaScript注入"
|
|||
msgid "Run command"
|
||||
msgstr "コマンドを実行する"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/remote-debug/remote-debug.html
|
||||
#: /Users/a12907/STF/stf/res/app/control-panes/dashboard/remote-debug/remote-debug-controller.js
|
||||
msgid ""
|
||||
"Run the following on your command line to debug the device from your Browser"
|
||||
msgstr ""
|
||||
"次のコマンドをコマンドラインで実行しますと、お使いのブラウザより端末のデバッ"
|
||||
"グができます。"
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/control-panes/dashboard/remote-debug/remote-debug-controller.js
|
||||
msgid ""
|
||||
"Run the following on your command line to debug the device from your IDE"
|
||||
msgstr ""
|
||||
"次のコマンドをコマンドラインで実行しますと、お使いのIDEより端末のデバッグがで"
|
||||
"きます。"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/advanced/remote-debug/remote-debug.html
|
||||
msgid "Run the following on your command line:"
|
||||
msgstr "次のコマンドをコマンドラインで実行してください。"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/info/info.html
|
||||
msgid "SD Card Mounted"
|
||||
msgstr "SDカード"
|
||||
|
@ -980,6 +969,14 @@ msgstr "サインイン"
|
|||
msgid "Sign Out"
|
||||
msgstr "サインアウト"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/automation/device-settings/device-settings.html
|
||||
msgid "Silent Mode"
|
||||
msgstr "マナーモード"
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/socket/socket-state/socket-state-directive.js
|
||||
msgid "Socket connection was lost, try again reloading the page."
|
||||
msgstr "接続が切れました。ページをリロードしてみてください。"
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/device/device-info-filter/index.js
|
||||
msgid "Someone stole your device."
|
||||
msgstr "誰かはデバイスを盗みました。"
|
||||
|
@ -1111,10 +1108,15 @@ msgid "Upload complete"
|
|||
msgstr "アップロードが完了しました"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/upload/upload.html
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/upload/upload-error-filter.js
|
||||
msgid "Upload failed"
|
||||
msgstr "アップロードが失敗しました"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/upload/upload.html
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/upload/upload-error-filter.js
|
||||
msgid "Upload unknown error"
|
||||
msgstr "アップロード未知エラー"
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/upload/upload-error-filter.js
|
||||
msgid "Uploaded file is not valid"
|
||||
msgstr "アップロードされたファイル"
|
||||
|
||||
|
@ -1162,6 +1164,10 @@ msgstr "バージョン"
|
|||
msgid "Version Update"
|
||||
msgstr "バージョンアップ"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/automation/device-settings/device-settings.html
|
||||
msgid "Vibrate Mode"
|
||||
msgstr "マナーモード(バイブON)"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/info/info.html
|
||||
msgid "Voltage"
|
||||
msgstr "電圧"
|
||||
|
@ -1186,6 +1192,10 @@ msgstr "Web"
|
|||
msgid "WiFi"
|
||||
msgstr "無線LAN"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/automation/device-settings/device-settings.html
|
||||
msgid "WiFi Enabled"
|
||||
msgstr "無線LAN:ON"
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/apps/apps.html
|
||||
msgid "WiFi Settings"
|
||||
msgstr "無線LAN設定"
|
||||
|
@ -1230,6 +1240,21 @@ msgstr "{{ device.enhancedName }}のステータス:"
|
|||
msgid "{{ device.enhancedName }} was disconnected"
|
||||
msgstr "{{ device.enhancedName }}への接続が切れました"
|
||||
|
||||
#~ msgid "Browser"
|
||||
#~ msgstr "ブラウザ"
|
||||
|
||||
#~ msgid "Reference"
|
||||
#~ msgstr "参考"
|
||||
|
||||
#~ msgid "Relaunch"
|
||||
#~ msgstr "再起動"
|
||||
|
||||
#~ msgid "Relaunch the browser"
|
||||
#~ msgstr "ブラウザを再起動する"
|
||||
|
||||
#~ msgid "Run the following on your command line:"
|
||||
#~ msgstr "次のコマンドをコマンドラインで実行してください。"
|
||||
|
||||
#~ msgid "Remove Accounts"
|
||||
#~ msgstr "アカウント削除"
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ msgstr ""
|
|||
msgid "Camera"
|
||||
msgstr ""
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/upload/upload.html
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/upload/upload-error-filter.js
|
||||
msgid "Cannot access specified URL"
|
||||
msgstr ""
|
||||
|
||||
|
@ -329,10 +329,6 @@ msgstr ""
|
|||
msgid "Encrypted"
|
||||
msgstr ""
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/upload/upload.html
|
||||
msgid "Error"
|
||||
msgstr ""
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/control/control-service.js
|
||||
msgid "Error while getting data"
|
||||
msgstr ""
|
||||
|
@ -345,6 +341,10 @@ msgstr ""
|
|||
msgid "Error."
|
||||
msgstr ""
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/upload/upload.html
|
||||
msgid "Error:"
|
||||
msgstr ""
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/control-panes/advanced/port-forwarding/port-forwarding-controller.js
|
||||
msgid "Error: Forwarding ports failed."
|
||||
msgstr ""
|
||||
|
@ -357,7 +357,7 @@ msgstr ""
|
|||
msgid "FPS"
|
||||
msgstr ""
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/upload/upload.html
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/upload/upload-error-filter.js
|
||||
msgid "Failed to download file"
|
||||
msgstr ""
|
||||
|
||||
|
@ -584,6 +584,10 @@ msgstr ""
|
|||
msgid "Network"
|
||||
msgstr ""
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/install/install-error-filter.js
|
||||
msgid "New package failed because the current SDK version is older than that required by the package"
|
||||
msgstr ""
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/advanced/input/input.html
|
||||
msgid "Next"
|
||||
msgstr ""
|
||||
|
@ -1086,10 +1090,15 @@ msgid "Upload complete"
|
|||
msgstr ""
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/upload/upload.html
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/upload/upload-error-filter.js
|
||||
msgid "Upload failed"
|
||||
msgstr ""
|
||||
|
||||
#: /Users/a12907/STF/stf/tmp/html/app/control-panes/dashboard/upload/upload.html
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/upload/upload-error-filter.js
|
||||
msgid "Upload unknown error"
|
||||
msgstr ""
|
||||
|
||||
#: /Users/a12907/STF/stf/res/app/components/stf/upload/upload-error-filter.js
|
||||
msgid "Uploaded file is not valid"
|
||||
msgstr ""
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue