mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge pull request #5171 from overleaf/jpa-web-launchpad-de-ng
[web] de-ng launchpad page GitOrigin-RevId: 0a8939ac8716bd099d9e8c2be0a281f24274e48d
This commit is contained in:
parent
9ae0d4a691
commit
f06f1e2b96
8 changed files with 267 additions and 389 deletions
|
@ -146,7 +146,7 @@ function formSentHelper(el) {
|
|||
})
|
||||
}
|
||||
|
||||
function toggleDisplay(hide, show) {
|
||||
export function toggleDisplay(hide, show) {
|
||||
hide.forEach(el => {
|
||||
el.hidden = true
|
||||
})
|
||||
|
|
|
@ -102,7 +102,9 @@ module.exports = LaunchpadController = {
|
|||
const { email } = req.body
|
||||
if (!email) {
|
||||
logger.log({}, 'no email address supplied')
|
||||
return res.sendStatus(400)
|
||||
return res.status(400).json({
|
||||
message: 'no email address supplied',
|
||||
})
|
||||
}
|
||||
logger.log({ email }, 'sending test email')
|
||||
const emailOptions = { to: email }
|
||||
|
@ -114,7 +116,7 @@ module.exports = LaunchpadController = {
|
|||
return next(err)
|
||||
}
|
||||
logger.log({ email }, 'sent test email')
|
||||
return res.sendStatus(201)
|
||||
res.json({ message: res.locals.translate('email_sent') })
|
||||
})
|
||||
},
|
||||
|
||||
|
@ -245,19 +247,11 @@ module.exports = LaunchpadController = {
|
|||
return next(err)
|
||||
}
|
||||
|
||||
AuthenticationController.setRedirectInSession(req, '/launchpad')
|
||||
logger.log(
|
||||
{ email, user_id: user._id },
|
||||
'created first admin account'
|
||||
)
|
||||
return res.json({
|
||||
redir: '',
|
||||
id: user._id.toString(),
|
||||
first_name: user.first_name,
|
||||
last_name: user.last_name,
|
||||
email: user.email,
|
||||
created: Date.now(),
|
||||
})
|
||||
res.json({ redir: '/launchpad' })
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,24 +1,37 @@
|
|||
extends ../../../../app/views/layout
|
||||
extends ../../../../app/views/layout-marketing
|
||||
|
||||
mixin launchpad-check(section)
|
||||
div(data-ol-launchpad-check=section)
|
||||
span(data-ol-inflight="pending")
|
||||
i.fa.fa-fw.fa-spinner.fa-spin
|
||||
span #{translate('checking')}
|
||||
|
||||
span(hidden data-ol-inflight="idle")
|
||||
div(data-ol-result="success")
|
||||
i.fa.fa-check
|
||||
span #{translate('ok')}
|
||||
button.btn.btn-inline-link
|
||||
span.text-danger #{translate('retry')}
|
||||
div(hidden data-ol-result="error")
|
||||
i.fa.fa-exclamation
|
||||
span #{translate('error')}
|
||||
button.btn.btn-inline-link
|
||||
span.text-danger #{translate('retry')}
|
||||
div.alert.alert-danger
|
||||
span(data-ol-error)
|
||||
|
||||
block vars
|
||||
- entrypoint = 'modules/launchpad/pages/launchpad'
|
||||
- metadata = metadata || {}
|
||||
|
||||
block append meta
|
||||
meta(name="ol-adminUserExists" data-type="boolean" content=adminUserExists)
|
||||
meta(name="ol-ideJsPath" content=buildJsPath('ide.js'))
|
||||
meta(name="ol-authMethod" content=authMethod)
|
||||
|
||||
block content
|
||||
script(type="text/javascript", nonce=scriptNonce, src=(wsUrl || '/socket.io') + '/socket.io.js')
|
||||
|
||||
style.
|
||||
hr { margin-bottom: 5px; }
|
||||
.status-check {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.alert { margin-top: 15px; margin-bottom: 15px; }
|
||||
a small { cursor: pointer; color: #a93529; }
|
||||
.launchpad-body img { width: 150px; margin-top: 15px; }
|
||||
|
||||
|
||||
.content.content-alt(ng-controller="LaunchpadController")
|
||||
.content.content-alt
|
||||
.container(ng-cloak)
|
||||
.row
|
||||
.col-md-8.col-md-offset-2
|
||||
|
@ -36,191 +49,133 @@ block content
|
|||
|
||||
|
||||
<!-- create first admin form -->
|
||||
.row(ng-if="shouldShowAdminForm()")
|
||||
.col-md-12
|
||||
h2 #{translate('create_first_admin_account')}
|
||||
if !adminUserExists
|
||||
.row(data-ol-not-sent)
|
||||
.col-md-12
|
||||
h2 #{translate('create_first_admin_account')}
|
||||
|
||||
// Local Auth Form
|
||||
div(ng-if="authMethod == 'local'")
|
||||
form(async-form="register", name="registerForm", on-success="onCreateAdminSuccess"
|
||||
on-error="onCreateAdminError"
|
||||
action="/launchpad/register_admin", method="POST", ng-cloak)
|
||||
input(name='_csrf', type='hidden', value=csrfToken)
|
||||
form-messages(for="registerForm")
|
||||
.form-group
|
||||
label(for='email') #{translate("email")}
|
||||
input.form-control(
|
||||
type='email',
|
||||
name='email',
|
||||
placeholder="email@example.com"
|
||||
required,
|
||||
ng-model="email",
|
||||
ng-model-options="{ updateOn: 'blur' }",
|
||||
autofocus="true"
|
||||
)
|
||||
span.small.text-primary(ng-show="registerForm.email.$invalid && registerForm.email.$dirty")
|
||||
| #{translate("must_be_email_address")}
|
||||
.form-group
|
||||
label(for='password') #{translate("password")}
|
||||
input.form-control#passwordField(
|
||||
type='password',
|
||||
name='password',
|
||||
placeholder="********",
|
||||
required,
|
||||
ng-model="password",
|
||||
complex-password
|
||||
)
|
||||
span.small.text-primary(ng-show="registerForm.password.$error.complexPassword",
|
||||
ng-bind-html="complexPasswordErrorMessage")
|
||||
.actions
|
||||
button.btn-primary.btn(
|
||||
type='submit'
|
||||
ng-disabled="registerForm.inflight || registerForm.password.$error.required|| registerForm.password.$error.complexPassword || createAdminSuccess"
|
||||
)
|
||||
span(ng-show="!registerForm.inflight") #{translate("register")}
|
||||
span(ng-show="registerForm.inflight") #{translate("registering")}…
|
||||
// Local Auth Form
|
||||
if authMethod === 'local'
|
||||
form(
|
||||
data-ol-async-form
|
||||
data-ol-register-admin
|
||||
action="/launchpad/register_admin"
|
||||
method="POST"
|
||||
)
|
||||
input(name='_csrf', type='hidden', value=csrfToken)
|
||||
div(data-ol-form-messages)
|
||||
.form-group
|
||||
label(for='email') #{translate("email")}
|
||||
input.form-control(
|
||||
type='email',
|
||||
name='email',
|
||||
placeholder="email@example.com"
|
||||
required,
|
||||
autofocus="true"
|
||||
)
|
||||
.form-group
|
||||
label(for='password') #{translate("password")}
|
||||
input.form-control#passwordField(
|
||||
type='password',
|
||||
name='password',
|
||||
placeholder="********",
|
||||
required,
|
||||
)
|
||||
.actions
|
||||
button.btn-primary.btn(
|
||||
type='submit'
|
||||
data-ol-disabled-inflight
|
||||
)
|
||||
span(data-ol-inflight="idle") #{translate("register")}
|
||||
span(hidden data-ol-inflight="pending") #{translate("registering")}…
|
||||
|
||||
// Ldap Form
|
||||
div(ng-if="authMethod == 'ldap'")
|
||||
h3 #{translate('ldap')}
|
||||
p
|
||||
| #{translate('ldap_create_admin_instructions')}
|
||||
// Ldap Form
|
||||
if authMethod === 'ldap'
|
||||
h3 #{translate('ldap')}
|
||||
p
|
||||
| #{translate('ldap_create_admin_instructions')}
|
||||
|
||||
form(async-form="register", name="registerLdapForm", on-success="onCreateAdminSuccess"
|
||||
on-error="onCreateAdminError"
|
||||
action="/launchpad/register_ldap_admin", method="POST", ng-cloak)
|
||||
input(name='_csrf', type='hidden', value=csrfToken)
|
||||
form-messages(for="registerLdapForm")
|
||||
.form-group
|
||||
label(for='email') #{translate("email")}
|
||||
input.form-control(
|
||||
type='email',
|
||||
name='email',
|
||||
placeholder="email@example.com"
|
||||
required,
|
||||
ng-model="email",
|
||||
ng-model-options="{ updateOn: 'blur' }",
|
||||
autofocus="true"
|
||||
)
|
||||
span.small.text-primary(ng-show="registerLdapForm.email.$invalid && registerLdapForm.email.$dirty")
|
||||
| #{translate("must_be_email_address")}
|
||||
.actions
|
||||
button.btn-primary.btn(
|
||||
type='submit'
|
||||
ng-disabled="registerLdapForm.inflight || registerLdapForm.password.$error.required|| registerLdapForm.password.$error.complexPassword || createAdminSuccess"
|
||||
)
|
||||
span(ng-show="!registerLdapForm.inflight") #{translate("register")}
|
||||
span(ng-show="registerLdapForm.inflight") #{translate("registering")}…
|
||||
form(
|
||||
data-ol-async-form
|
||||
data-ol-register-admin
|
||||
action="/launchpad/register_ldap_admin"
|
||||
method="POST"
|
||||
)
|
||||
input(name='_csrf', type='hidden', value=csrfToken)
|
||||
div(data-ol-form-messages)
|
||||
.form-group
|
||||
label(for='email') #{translate("email")}
|
||||
input.form-control(
|
||||
type='email',
|
||||
name='email',
|
||||
placeholder="email@example.com"
|
||||
required,
|
||||
autofocus="true"
|
||||
)
|
||||
.actions
|
||||
button.btn-primary.btn(
|
||||
type='submit'
|
||||
data-ol-disabled-inflight
|
||||
)
|
||||
span(data-ol-inflight="idle") #{translate("register")}
|
||||
span(hidden data-ol-inflight="pending") #{translate("registering")}…
|
||||
|
||||
// Saml Form
|
||||
if authMethod === 'saml'
|
||||
h3 #{translate('saml')}
|
||||
p
|
||||
| #{translate('saml_create_admin_instructions')}
|
||||
|
||||
// Saml Form
|
||||
div(ng-if="authMethod == 'saml'")
|
||||
h3 #{translate('saml')}
|
||||
p
|
||||
| #{translate('saml_create_admin_instructions')}
|
||||
form(
|
||||
data-ol-async-form
|
||||
data-ol-register-admin
|
||||
action="/launchpad/register_saml_admin"
|
||||
method="POST"
|
||||
)
|
||||
input(name='_csrf', type='hidden', value=csrfToken)
|
||||
div(data-ol-form-messages)
|
||||
.form-group
|
||||
label(for='email') #{translate("email")}
|
||||
input.form-control(
|
||||
type='email',
|
||||
name='email',
|
||||
placeholder="email@example.com"
|
||||
required,
|
||||
autofocus="true"
|
||||
)
|
||||
.actions
|
||||
button.btn-primary.btn(
|
||||
type='submit'
|
||||
data-ol-disabled-inflight
|
||||
)
|
||||
span(data-ol-inflight="idle") #{translate("register")}
|
||||
span(hidden data-ol-inflight="pending") #{translate("registering")}…
|
||||
|
||||
form(async-form="register", name="registerSamlForm", on-success="onCreateAdminSuccess"
|
||||
on-error="onCreateAdminError"
|
||||
action="/launchpad/register_saml_admin", method="POST", ng-cloak)
|
||||
input(name='_csrf', type='hidden', value=csrfToken)
|
||||
form-messages(for="registerSamlForm")
|
||||
.form-group
|
||||
label(for='email') #{translate("email")}
|
||||
input.form-control(
|
||||
type='email',
|
||||
name='email',
|
||||
placeholder="email@example.com"
|
||||
required,
|
||||
ng-model="email",
|
||||
ng-model-options="{ updateOn: 'blur' }",
|
||||
autofocus="true"
|
||||
)
|
||||
span.small.text-primary(ng-show="registerSamlForm.email.$invalid && registerSamlForm.email.$dirty")
|
||||
| #{translate("must_be_email_address")}
|
||||
.actions
|
||||
button.btn-primary.btn(
|
||||
type='submit'
|
||||
ng-disabled="registerSamlForm.inflight || registerSamlForm.password.$error.required|| registerSamlForm.password.$error.complexPassword || createAdminSuccess"
|
||||
)
|
||||
span(ng-show="!registerSamlForm.inflight") #{translate("register")}
|
||||
span(ng-show="registerSamlForm.inflight") #{translate("registering")}…
|
||||
br
|
||||
|
||||
|
||||
<!-- success message -->
|
||||
.row(ng-if="createAdminSuccess")
|
||||
.col-md-12.text-center
|
||||
.alert.alert-success
|
||||
| !{translate('admin_user_created_message', {link: '/login?redir=/launchpad'})}
|
||||
|
||||
<!-- error message -->
|
||||
.row(ng-if="createAdminError")
|
||||
.col-md-12.text-center
|
||||
.alert.alert-danger
|
||||
| #{translate('generic_something_went_wrong')}
|
||||
|
||||
br
|
||||
|
||||
<!-- status indicators -->
|
||||
div(ng-if="!shouldShowAdminForm()")
|
||||
<!-- status indicators -->
|
||||
if adminUserExists
|
||||
.row
|
||||
.col-md-12.status-indicators
|
||||
|
||||
h2 #{translate('status_checks')}
|
||||
|
||||
<!-- ide js -->
|
||||
.row.status-check
|
||||
.row.row-spaced-small
|
||||
.col-sm-5
|
||||
| #{translate('editor_resources')}
|
||||
.col-sm-7
|
||||
div(ng-switch="statusChecks.ideJs.status")
|
||||
|
||||
span(ng-switch-when="inflight")
|
||||
i.fa.fa-fw.fa-spinner.fa-spin
|
||||
span #{translate('checking')}
|
||||
|
||||
span(ng-switch-when="ok")
|
||||
i.fa.fa-check
|
||||
span #{translate('ok')}
|
||||
a(ng-click="tryFetchIdeJs()")
|
||||
small #{translate('retry')}
|
||||
|
||||
span(ng-switch-when="error")
|
||||
i.fa.fa-exclamation
|
||||
span #{translate('error')}
|
||||
a(ng-click="tryFetchIdeJs()")
|
||||
small #{translate('retry')}
|
||||
div.alert.alert-danger
|
||||
| {{ statusChecks.ideJs.error }}
|
||||
|
||||
+launchpad-check('ide')
|
||||
|
||||
<!-- websocket -->
|
||||
.row.status-check
|
||||
.row.row-spaced-small
|
||||
.col-sm-5
|
||||
| #{translate('websockets')}
|
||||
.col-sm-7
|
||||
div(ng-switch="statusChecks.websocket.status")
|
||||
|
||||
span(ng-switch-when="inflight")
|
||||
i.fa.fa-fw.fa-spinner.fa-spin
|
||||
span #{translate('checking')}
|
||||
|
||||
span(ng-switch-when="ok")
|
||||
i.fa.fa-check
|
||||
span #{translate('ok')}
|
||||
a(ng-click="tryOpenWebSocket()")
|
||||
small #{translate('retry')}
|
||||
|
||||
span(ng-switch-when="error")
|
||||
i.fa.fa-exclamation
|
||||
span #{translate('error')}
|
||||
a(ng-click="tryOpenWebSocket()")
|
||||
small #{translate('retry')}
|
||||
div.alert.alert-danger
|
||||
| {{ statusChecks.websocket.error }}
|
||||
|
||||
+launchpad-check('websocket')
|
||||
|
||||
<!-- break -->
|
||||
hr
|
||||
hr.thin
|
||||
|
||||
<!-- other actions -->
|
||||
.row
|
||||
|
@ -228,26 +183,33 @@ block content
|
|||
h2 #{translate('other_actions')}
|
||||
|
||||
h3 #{translate('send_test_email')}
|
||||
form.form
|
||||
form.form(
|
||||
data-ol-async-form
|
||||
action="/launchpad/send_test_email"
|
||||
method="POST"
|
||||
)
|
||||
.form-group
|
||||
label(for="emailInput") Email
|
||||
input(type="text", name="emailInput" ng-model="testEmail.emailAddress").form-control
|
||||
button(ng-click="sendTestEmail()", ng-disabled="testEmail.inflight").btn.btn-primary
|
||||
span(ng-show="!testEmail.inflight") #{translate("send")}
|
||||
span(ng-show="testEmail.inflight") #{translate("sending")}…
|
||||
div(ng-if="testEmail.status == 'ok'")
|
||||
.alert.alert-success
|
||||
| #{translate('email_sent')}
|
||||
div(ng-if="testEmail.status == 'error'")
|
||||
.alert.alert-danger
|
||||
| #{translate('generic_something_went_wrong')}
|
||||
|
||||
label(for="email") Email
|
||||
input.form-control(
|
||||
type="text"
|
||||
id="email"
|
||||
name="email"
|
||||
required
|
||||
)
|
||||
button.btn-primary.btn(
|
||||
type='submit'
|
||||
data-ol-disabled-inflight
|
||||
)
|
||||
span(data-ol-inflight="idle") #{translate("send")}
|
||||
span(hidden data-ol-inflight="pending") #{translate("sending")}…
|
||||
|
||||
p
|
||||
div(data-ol-form-messages)
|
||||
|
||||
|
||||
|
||||
<!-- break -->
|
||||
hr
|
||||
hr.thin
|
||||
|
||||
|
||||
<!-- Go to app -->
|
||||
|
|
|
@ -1,157 +0,0 @@
|
|||
/* global io */
|
||||
|
||||
/* eslint-disable
|
||||
max-len,
|
||||
no-return-assign,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
* decaffeinate suggestions:
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
import App from '../../../../../../frontend/js/base'
|
||||
|
||||
export default App.controller(
|
||||
'LaunchpadController',
|
||||
function ($scope, $http, $timeout) {
|
||||
$scope.adminUserExists = window.data.adminUserExists
|
||||
$scope.ideJsPath = window.data.ideJsPath
|
||||
$scope.authMethod = window.data.authMethod
|
||||
|
||||
$scope.createAdminSuccess = null
|
||||
$scope.createAdminError = null
|
||||
|
||||
$scope.statusChecks = {
|
||||
ideJs: { status: 'inflight', error: null },
|
||||
websocket: { status: 'inflight', error: null },
|
||||
healthCheck: { status: 'inflight', error: null },
|
||||
}
|
||||
|
||||
$scope.testEmail = {
|
||||
emailAddress: '',
|
||||
inflight: false,
|
||||
status: null, // | 'ok' | 'success'
|
||||
}
|
||||
|
||||
$scope.shouldShowAdminForm = () => !$scope.adminUserExists
|
||||
|
||||
$scope.onCreateAdminSuccess = function (response) {
|
||||
const { status } = response
|
||||
if (status >= 200 && status < 300) {
|
||||
return ($scope.createAdminSuccess = true)
|
||||
}
|
||||
}
|
||||
|
||||
$scope.onCreateAdminError = () => ($scope.createAdminError = true)
|
||||
|
||||
$scope.sendTestEmail = function () {
|
||||
$scope.testEmail.inflight = true
|
||||
$scope.testEmail.status = null
|
||||
return $http
|
||||
.post('/launchpad/send_test_email', {
|
||||
email: $scope.testEmail.emailAddress,
|
||||
_csrf: window.csrfToken,
|
||||
})
|
||||
.then(function (response) {
|
||||
const { status } = response
|
||||
$scope.testEmail.inflight = false
|
||||
if (status >= 200 && status < 300) {
|
||||
return ($scope.testEmail.status = 'ok')
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
$scope.testEmail.inflight = false
|
||||
return ($scope.testEmail.status = 'error')
|
||||
})
|
||||
}
|
||||
|
||||
$scope.tryFetchIdeJs = function () {
|
||||
$scope.statusChecks.ideJs.status = 'inflight'
|
||||
return $timeout(
|
||||
() =>
|
||||
$http
|
||||
.get($scope.ideJsPath)
|
||||
.then(function (response) {
|
||||
const { status } = response
|
||||
if (status >= 200 && status < 300) {
|
||||
return ($scope.statusChecks.ideJs.status = 'ok')
|
||||
}
|
||||
})
|
||||
.catch(function (response) {
|
||||
const { status } = response
|
||||
$scope.statusChecks.ideJs.status = 'error'
|
||||
return ($scope.statusChecks.ideJs.error = new Error(
|
||||
`Http status: ${status}`
|
||||
))
|
||||
}),
|
||||
|
||||
1000
|
||||
)
|
||||
}
|
||||
|
||||
$scope.tryOpenWebSocket = function () {
|
||||
$scope.statusChecks.websocket.status = 'inflight'
|
||||
return $timeout(function () {
|
||||
if (typeof io === 'undefined' || io === null) {
|
||||
$scope.statusChecks.websocket.status = 'error'
|
||||
$scope.statusChecks.websocket.error = 'socket.io not loaded'
|
||||
return
|
||||
}
|
||||
const socket = io.connect(null, {
|
||||
reconnect: false,
|
||||
'connect timeout': 30 * 1000,
|
||||
'force new connection': true,
|
||||
})
|
||||
|
||||
socket.on('connectionAccepted', function () {
|
||||
$scope.statusChecks.websocket.status = 'ok'
|
||||
return $scope.$apply(function () {})
|
||||
})
|
||||
|
||||
socket.on('connectionRejected', function (err) {
|
||||
$scope.statusChecks.websocket.status = 'error'
|
||||
$scope.statusChecks.websocket.error = err
|
||||
return $scope.$apply(function () {})
|
||||
})
|
||||
|
||||
return socket.on('connect_failed', function (err) {
|
||||
$scope.statusChecks.websocket.status = 'error'
|
||||
$scope.statusChecks.websocket.error = err
|
||||
return $scope.$apply(function () {})
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
$scope.tryHealthCheck = function () {
|
||||
$scope.statusChecks.healthCheck.status = 'inflight'
|
||||
return $http
|
||||
.get('/health_check')
|
||||
.then(function (response) {
|
||||
const { status } = response
|
||||
if (status >= 200 && status < 300) {
|
||||
return ($scope.statusChecks.healthCheck.status = 'ok')
|
||||
}
|
||||
})
|
||||
.catch(function (response) {
|
||||
const { status } = response
|
||||
$scope.statusChecks.healthCheck.status = 'error'
|
||||
return ($scope.statusChecks.healthCheck.error = new Error(
|
||||
`Http status: ${status}`
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
$scope.runStatusChecks = function () {
|
||||
$timeout(() => $scope.tryFetchIdeJs(), 1000)
|
||||
return $timeout(() => $scope.tryOpenWebSocket(), 2000)
|
||||
}
|
||||
|
||||
// kick off the status checks on load
|
||||
if ($scope.adminUserExists) {
|
||||
return $scope.runStatusChecks()
|
||||
}
|
||||
}
|
||||
)
|
|
@ -1,3 +0,0 @@
|
|||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Sanity-check the conversion and remove this comment.
|
||||
import './controllers/LaunchpadController'
|
|
@ -0,0 +1,88 @@
|
|||
/* global io */
|
||||
import '../../../../../frontend/js/marketing'
|
||||
import {
|
||||
inflightHelper,
|
||||
toggleDisplay,
|
||||
} from '../../../../../frontend/js/features/form-helpers/hydrate-form'
|
||||
import getMeta from '../../../../../frontend/js/utils/meta'
|
||||
|
||||
function setUpStatusIndicator(el, fn) {
|
||||
inflightHelper(el)
|
||||
|
||||
const displaySuccess = el.querySelectorAll('[data-ol-result="success"]')
|
||||
const displayError = el.querySelectorAll('[data-ol-result="error"]')
|
||||
|
||||
// The checks are very lightweight and do not appear to do anything
|
||||
// from looking at the UI. Add an artificial delay of 1s to show that
|
||||
// we are actually doing something. :)
|
||||
const artificialProgressDelay = 1000
|
||||
|
||||
function run() {
|
||||
setTimeout(() => {
|
||||
fn()
|
||||
.then(() => {
|
||||
toggleDisplay(displayError, displaySuccess)
|
||||
})
|
||||
.catch(error => {
|
||||
el.querySelector('[data-ol-error]').textContent = error.message
|
||||
toggleDisplay(displaySuccess, displayError)
|
||||
})
|
||||
.finally(() => {
|
||||
el.dispatchEvent(new Event('idle'))
|
||||
})
|
||||
}, artificialProgressDelay)
|
||||
}
|
||||
|
||||
el.querySelectorAll('button').forEach(retryBtn => {
|
||||
retryBtn.addEventListener('click', function (e) {
|
||||
e.preventDefault()
|
||||
el.dispatchEvent(new Event('pending'))
|
||||
run()
|
||||
})
|
||||
})
|
||||
|
||||
run()
|
||||
}
|
||||
|
||||
function setUpStatusIndicators() {
|
||||
setUpStatusIndicator(
|
||||
document.querySelector('[data-ol-launchpad-check="websocket"]'),
|
||||
() => {
|
||||
const timeout = 10 * 1000
|
||||
const socket = io.connect(null, {
|
||||
reconnect: false,
|
||||
'connect timeout': timeout,
|
||||
'force new connection': true,
|
||||
})
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => reject(new Error('timed out')), timeout)
|
||||
socket.on('connectionAccepted', function () {
|
||||
resolve()
|
||||
})
|
||||
socket.on('connectionRejected', function (err) {
|
||||
reject(new Error(err && err.message))
|
||||
})
|
||||
socket.on('connect_failed', function (err) {
|
||||
reject(new Error(err && err.message))
|
||||
})
|
||||
}).finally(() => {
|
||||
socket.disconnect()
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
setUpStatusIndicator(
|
||||
document.querySelector('[data-ol-launchpad-check="ide"]'),
|
||||
() => {
|
||||
return fetch(getMeta('ol-ideJsPath')).then(res => {
|
||||
if (!res.ok) {
|
||||
throw new Error(`Http status: ${res.status}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (getMeta('ol-adminUserExists')) {
|
||||
setUpStatusIndicators()
|
||||
}
|
|
@ -37,9 +37,7 @@ describe('Launchpad', function () {
|
|||
},
|
||||
})
|
||||
expect(postResponse.statusCode).to.equal(200)
|
||||
expect(postResponse.body.redir).to.equal('')
|
||||
expect(postResponse.body.email).to.equal(adminEmail)
|
||||
expect(postResponse.body.id).to.exist
|
||||
expect(postResponse.body).to.deep.equal({ redir: '/launchpad' })
|
||||
|
||||
// Try to load the page again
|
||||
const secondPageResponse = await user.request.get('/launchpad', {
|
||||
|
|
|
@ -53,9 +53,16 @@ describe('LaunchpadController', function () {
|
|||
this.res = {
|
||||
render: sinon.stub(),
|
||||
redirect: sinon.stub(),
|
||||
json: sinon.stub(),
|
||||
send: sinon.stub(),
|
||||
sendStatus: sinon.stub(),
|
||||
locals: {
|
||||
translate(key) {
|
||||
return key
|
||||
},
|
||||
},
|
||||
}
|
||||
this.res.status = sinon.stub().returns(this.res)
|
||||
|
||||
return (this.next = sinon.stub())
|
||||
})
|
||||
|
@ -252,10 +259,13 @@ describe('LaunchpadController', function () {
|
|||
return (this.next = sinon.stub())
|
||||
})
|
||||
|
||||
it('should produce a 201 response', function () {
|
||||
it('should produce a 200 response', function () {
|
||||
this.LaunchpadController.sendTestEmail(this.req, this.res, this.next)
|
||||
this.res.sendStatus.callCount.should.equal(1)
|
||||
return this.res.sendStatus.calledWith(201).should.equal(true)
|
||||
this.res.json
|
||||
.calledWith({
|
||||
message: 'email_sent',
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should not call next with an error', function () {
|
||||
|
@ -292,8 +302,12 @@ describe('LaunchpadController', function () {
|
|||
|
||||
it('should produce a 400 response', function () {
|
||||
this.LaunchpadController.sendTestEmail(this.req, this.res, this.next)
|
||||
this.res.sendStatus.callCount.should.equal(1)
|
||||
return this.res.sendStatus.calledWith(400).should.equal(true)
|
||||
this.res.status.calledWith(400).should.equal(true)
|
||||
this.res.json
|
||||
.calledWith({
|
||||
message: 'no email address supplied',
|
||||
})
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -337,7 +351,7 @@ describe('LaunchpadController', function () {
|
|||
|
||||
it('should send back a json response', function () {
|
||||
this.res.json.callCount.should.equal(1)
|
||||
return expect(this.res.json.lastCall.args[0].email).to.equal(this.email)
|
||||
expect(this.res.json).to.have.been.calledWith({ redir: '/launchpad' })
|
||||
})
|
||||
|
||||
it('should have checked for existing admins', function () {
|
||||
|
@ -365,15 +379,6 @@ describe('LaunchpadController', function () {
|
|||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should have set a redirect in session', function () {
|
||||
this.AuthenticationController.setRedirectInSession.callCount.should.equal(
|
||||
1
|
||||
)
|
||||
return this.AuthenticationController.setRedirectInSession
|
||||
.calledWith(this.req, '/launchpad')
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when no email is supplied', function () {
|
||||
|
@ -648,7 +653,7 @@ describe('LaunchpadController', function () {
|
|||
|
||||
it('should send back a json response', function () {
|
||||
this.res.json.callCount.should.equal(1)
|
||||
return expect(this.res.json.lastCall.args[0].email).to.equal(this.email)
|
||||
expect(this.res.json).to.have.been.calledWith({ redir: '/launchpad' })
|
||||
})
|
||||
|
||||
it('should have checked for existing admins', function () {
|
||||
|
@ -675,15 +680,6 @@ describe('LaunchpadController', function () {
|
|||
)
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should have set a redirect in session', function () {
|
||||
this.AuthenticationController.setRedirectInSession.callCount.should.equal(
|
||||
1
|
||||
)
|
||||
return this.AuthenticationController.setRedirectInSession
|
||||
.calledWith(this.req, '/launchpad')
|
||||
.should.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in a new issue