From 2a935d7ab55581204e431ab782b4bba1b5b7c0a1 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Wed, 29 Sep 2021 11:04:58 +0200 Subject: [PATCH] Merge pull request #5261 from overleaf/jpa-de-ng-more-complex-pages [web] de-ng some of the complex pages GitOrigin-RevId: 6c85bbf2d21cb2e8d3441202dfd299512bf71453 --- .../app/views/_mixins/bookmarkable_tabset.pug | 9 + services/web/app/views/admin/index.pug | 160 ++++++++++-------- .../web/app/views/general/post-gateway.pug | 15 +- services/web/app/views/user/sessions.pug | 72 ++++---- .../js/features/form-helpers/hydrate-form.js | 16 +- services/web/frontend/js/main.js | 1 - services/web/frontend/js/main/post-gateway.js | 18 -- services/web/frontend/js/marketing.js | 1 + 8 files changed, 162 insertions(+), 130 deletions(-) create mode 100644 services/web/app/views/_mixins/bookmarkable_tabset.pug delete mode 100644 services/web/frontend/js/main/post-gateway.js diff --git a/services/web/app/views/_mixins/bookmarkable_tabset.pug b/services/web/app/views/_mixins/bookmarkable_tabset.pug new file mode 100644 index 0000000000..3f43b0c4ce --- /dev/null +++ b/services/web/app/views/_mixins/bookmarkable_tabset.pug @@ -0,0 +1,9 @@ +mixin bookmarkable-tabset-header(id, title, active) + li(role="presentation" class=(active ? 'active' : '')) + a( + href='#' + id + aria-controls=id + role="tab" + data-toggle="tab" + data-ol-bookmarkable-tab + ) #{title} diff --git a/services/web/app/views/admin/index.pug b/services/web/app/views/admin/index.pug index a2dd4a8d1b..eac8faf8bc 100644 --- a/services/web/app/views/admin/index.pug +++ b/services/web/app/views/admin/index.pug @@ -1,4 +1,5 @@ -extends ../layout +extends ../layout-marketing +include ../_mixins/bookmarkable_tabset block content .content.content-alt @@ -8,77 +9,100 @@ block content .card .page-header h1 Admin Panel - tabset(bookmarkable-tabset ng-cloak) - tab(heading="System Messages" bookmarkable-tab="system-messages") - each message in systemMessages - .alert.alert-info.row-spaced(ng-non-bindable) #{message.content} - hr - form(method='post', action='/admin/messages') - input(name="_csrf", type="hidden", value=csrfToken) - .form-group - label(for="content") - input.form-control(name="content", type="text", placeholder="Message…", required) - button.btn.btn-primary(type="submit") Post Message - hr - form(method='post', action='/admin/messages/clear') - input(name="_csrf", type="hidden", value=csrfToken) - button.btn.btn-danger(type="submit") Clear all messages - - - tab(heading="Open Sockets" bookmarkable-tab="open-sockets") - .row-spaced - ul - each agents, url in openSockets - li(ng-non-bindable) #{url} - total : #{agents.length} - ul - each agent in agents - li(ng-non-bindable) #{agent} - - tab(heading="Open/Close Editor" bookmarkable-tab="open-close-editor") + div(data-ol-bookmarkable-tabset) + ul.nav.nav-tabs(role="tablist") + +bookmarkable-tabset-header('system-messages', 'System Messages', true) + +bookmarkable-tabset-header('open-sockets', 'Open Sockets') + +bookmarkable-tabset-header('open-close-editor', 'Open/Close Editor') if hasFeature('saas') - | The "Open/Close Editor" feature is not available in SAAS. - else - .row-spaced - form(method='post',action='/admin/closeEditor') - input(name="_csrf", type="hidden", value=csrfToken) - button.btn.btn-danger(type="submit") Close Editor - p.small Will stop anyone opening the editor. Will NOT disconnect already connected users. + +bookmarkable-tabset-header('tpds', 'TPDS/Dropbox Management') + +bookmarkable-tabset-header('advanced', 'Advanced') - .row-spaced - form(method='post',action='/admin/disconnectAllUsers') - input(name="_csrf", type="hidden", value=csrfToken) - button.btn.btn-danger(type="submit") Disconnect all users - p.small Will force disconnect all users with the editor open. Make sure to close the editor first to avoid them reconnecting. - - .row-spaced - form(method='post',action='/admin/openEditor') - input(name="_csrf", type="hidden", value=csrfToken) - button.btn.btn-danger(type="submit") Reopen Editor - p.small Will reopen the editor after closing. - - if hasFeature('saas') - tab(heading="TPDS/Dropbox Management" bookmarkable-tab="tpds") - h3 Flush project to TPDS - .row - form.col-xs-6(method='post',action='/admin/flushProjectToTpds') - input(name="_csrf", type="hidden", value=csrfToken) - .form-group - label(for='project_id') project_id - input.form-control(type='text', name='project_id', placeholder='project_id', required) - .form-group - button.btn-primary.btn(type='submit') Flush + .tab-content + .tab-pane.active( + role="tabpanel" + id='system-messages' + ) + each message in systemMessages + .alert.alert-info.row-spaced(ng-non-bindable) #{message.content} hr - h3 Poll Dropbox for user - .row - form.col-xs-6(method='post',action='/admin/pollDropboxForUser') - input(name="_csrf", type="hidden", value=csrfToken) - .form-group - label(for='user_id') user_id - input.form-control(type='text', name='user_id', placeholder='user_id', required) - .form-group - button.btn-primary.btn(type='submit') Poll + form(method='post', action='/admin/messages') + input(name="_csrf", type="hidden", value=csrfToken) + .form-group + label(for="content") + input.form-control(name="content", type="text", placeholder="Message…", required) + button.btn.btn-primary(type="submit") Post Message + hr + form(method='post', action='/admin/messages/clear') + input(name="_csrf", type="hidden", value=csrfToken) + button.btn.btn-danger(type="submit") Clear all messages - tab(heading="Advanced" bookmarkable-tab="advanced") + .tab-pane( + role="tabpanel" + id='open-sockets' + ) + .row-spaced + ul + each agents, url in openSockets + li(ng-non-bindable) #{url} - total : #{agents.length} + ul + each agent in agents + li(ng-non-bindable) #{agent} + + .tab-pane( + role="tabpanel" + id='open-close-editor' + ) + if hasFeature('saas') + | The "Open/Close Editor" feature is not available in SAAS. + else + .row-spaced + form(method='post',action='/admin/closeEditor') + input(name="_csrf", type="hidden", value=csrfToken) + button.btn.btn-danger(type="submit") Close Editor + p.small Will stop anyone opening the editor. Will NOT disconnect already connected users. + + .row-spaced + form(method='post',action='/admin/disconnectAllUsers') + input(name="_csrf", type="hidden", value=csrfToken) + button.btn.btn-danger(type="submit") Disconnect all users + p.small Will force disconnect all users with the editor open. Make sure to close the editor first to avoid them reconnecting. + + .row-spaced + form(method='post',action='/admin/openEditor') + input(name="_csrf", type="hidden", value=csrfToken) + button.btn.btn-danger(type="submit") Reopen Editor + p.small Will reopen the editor after closing. + + if hasFeature('saas') + .tab-pane( + role="tabpanel" + id='tpds' + ) + h3 Flush project to TPDS + .row + form.col-xs-6(method='post',action='/admin/flushProjectToTpds') + input(name="_csrf", type="hidden", value=csrfToken) + .form-group + label(for='project_id') project_id + input.form-control(type='text', name='project_id', placeholder='project_id', required) + .form-group + button.btn-primary.btn(type='submit') Flush + hr + h3 Poll Dropbox for user + .row + form.col-xs-6(method='post',action='/admin/pollDropboxForUser') + input(name="_csrf", type="hidden", value=csrfToken) + .form-group + label(for='user_id') user_id + input.form-control(type='text', name='user_id', placeholder='user_id', required) + .form-group + button.btn-primary.btn(type='submit') Poll + + .tab-pane( + role="tabpanel" + id='advanced' + ) .row-spaced form(method='post',action='/admin/unregisterServiceWorker') input(name="_csrf", type="hidden", value=csrfToken) diff --git a/services/web/app/views/general/post-gateway.pug b/services/web/app/views/general/post-gateway.pug index 8be63d516d..428b5f3094 100644 --- a/services/web/app/views/general/post-gateway.pug +++ b/services/web/app/views/general/post-gateway.pug @@ -1,4 +1,4 @@ -extends ../layout +extends ../layout-marketing block vars - var suppressNavbar = true @@ -6,8 +6,6 @@ block vars - var suppressSkipToContent = true block content - script(type="template", id="gateway-data")!= StringHelper.stringifyJsonForScript({ params: form_data }) - .content.content-alt .container .row @@ -16,6 +14,11 @@ block content p.text-center #{translate('processing_your_request')} form( - ng-controller="PostGatewayController", - ng-init="handleGateway();" - id='gateway' method='POST') + data-ol-regular-form + data-ol-auto-submit + method="POST" + ) + input(name="_csrf" type="hidden" value=csrfToken) + input(hidden name="viaGateway" type="submit" value="true") + for name in Object.keys(form_data) + input(name=name type="hidden" value=form_data[name]) diff --git a/services/web/app/views/user/sessions.pug b/services/web/app/views/user/sessions.pug index 315aa06ae1..708a909849 100644 --- a/services/web/app/views/user/sessions.pug +++ b/services/web/app/views/user/sessions.pug @@ -1,16 +1,11 @@ -extends ../layout - - -block append meta - meta(name="ol-otherSessions" data-type="json" content=sessions) - +extends ../layout-marketing block content main.content.content-alt#main-content .container .row .col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 - .card.clear-user-sessions(ng-controller="ClearSessionsController", ng-cloak) + .card.clear-user-sessions .page-header h1 #{translate("your_sessions")} @@ -18,31 +13,44 @@ block content p.small | !{translate("clear_sessions_description")} - div - div(ng-if="state.otherSessions.length == 0") + form( + data-ol-async-form + action='/user/sessions/clear' + method='POST' + ) + input(name='_csrf' type='hidden' value=csrfToken) + div(data-ol-not-sent) + if sessions.length == 0 + p.text-center + | #{translate("no_other_sessions")} + + div(ng-if="state.success == true") + p.text-success.text-center + | #{translate('clear_sessions_success')} + + if sessions.length > 0 + table.table.table-striped + thead + tr + th #{translate("ip_address")} + th #{translate("session_created_at")} + for session in sessions + tr + td #{session.ip_address} + td #{moment(session.session_created).utc().format('Do MMM YYYY, h:mm a')} UTC + + p.actions + .text-center + button.btn.btn-lg.btn-primary( + type="submit" + data-ol-disable-inflight + ) + span(data-ol-inflight="idle") #{translate('clear_sessions')} + span(hidden data-ol-inflight="pending") #{translate("processing")}… + + div(hidden data-ol-sent) p.text-center | #{translate("no_other_sessions")} - div(ng-if="state.success == true") - p.text-success.text-center - | #{translate('clear_sessions_success')} - - div(ng-if="state.otherSessions.length != 0") - table.table.table-striped - thead - tr - th #{translate("ip_address")} - th #{translate("session_created_at")} - tr(ng-repeat="session in state.otherSessions") - td {{session.ip_address}} - td {{session.session_created | formatDate}} - - p.actions - .text-center - button.btn.btn-lg.btn-primary( - ng-click="clearSessions()" - ) #{translate('clear_sessions')} - - div(ng-if="state.error == true") - p.text-danger.error - | #{translate('generic_something_went_wrong')} + p.text-success.text-center + | #{translate('clear_sessions_success')} diff --git a/services/web/frontend/js/features/form-helpers/hydrate-form.js b/services/web/frontend/js/features/form-helpers/hydrate-form.js index 8e53119f3a..33ea70273a 100644 --- a/services/web/frontend/js/features/form-helpers/hydrate-form.js +++ b/services/web/frontend/js/features/form-helpers/hydrate-form.js @@ -56,11 +56,6 @@ function formSubmitHelper(formEl) { formEl.dispatchEvent(new Event('idle')) } }) - if (formEl.hasAttribute('data-ol-auto-submit')) { - setTimeout(() => { - formEl.querySelector('[type="submit"]').click() - }, 0) - } } async function validateCaptcha(formEl) { @@ -154,6 +149,14 @@ function formValidationHelper(el) { }) } +function formAutoSubmitHelper(el) { + if (el.hasAttribute('data-ol-auto-submit')) { + setTimeout(() => { + el.querySelector('[type="submit"]').click() + }, 0) + } +} + export function toggleDisplay(hide, show) { hide.forEach(el => { el.hidden = true @@ -168,6 +171,7 @@ function hydrateAsyncForm(el) { inflightHelper(el) formSentHelper(el) formValidationHelper(el) + formAutoSubmitHelper(el) } function hydrateRegularForm(el) { @@ -177,6 +181,8 @@ function hydrateRegularForm(el) { el.addEventListener('submit', () => { el.dispatchEvent(new Event('pending')) }) + + formAutoSubmitHelper(el) } document.querySelectorAll(`[data-ol-async-form]`).forEach(hydrateAsyncForm) diff --git a/services/web/frontend/js/main.js b/services/web/frontend/js/main.js index 1685e16ce0..b135bc5c5c 100644 --- a/services/web/frontend/js/main.js +++ b/services/web/frontend/js/main.js @@ -14,7 +14,6 @@ import './main/account-settings' import './main/clear-sessions' import './main/account-upgrade-angular' import './main/plans' -import './main/post-gateway' import './main/user-membership' import './main/scribtex-popup' import './main/event' diff --git a/services/web/frontend/js/main/post-gateway.js b/services/web/frontend/js/main/post-gateway.js deleted file mode 100644 index d029d941fe..0000000000 --- a/services/web/frontend/js/main/post-gateway.js +++ /dev/null @@ -1,18 +0,0 @@ -import App from '../base' - -export default App.controller('PostGatewayController', function ($scope) { - $scope.handleGateway = function () { - const { params } = JSON.parse($('#gateway-data').text()) - params.viaGateway = 'true' - Object.keys(params).forEach(param => { - $('') - .attr({ - type: 'hidden', - name: param, - value: params[param], - }) - .appendTo('#gateway') - }) - $('#gateway').submit() - } -}) diff --git a/services/web/frontend/js/marketing.js b/services/web/frontend/js/marketing.js index 6c9be38316..2deb67cb38 100644 --- a/services/web/frontend/js/marketing.js +++ b/services/web/frontend/js/marketing.js @@ -3,6 +3,7 @@ import 'jquery' import 'bootstrap' import './features/form-helpers/hydrate-form' import './features/link-helpers/slow-link' +import './features/bookmarkable-tab' import './features/contact-form' import './features/event-tracking' import './features/fallback-image'