Browse Source

Merge pull request #22717 from overleaf/rd-migrate-admin-bootstrap5

[web] Migrate the admin page to Bootstrap 5

GitOrigin-RevId: 8d283f7ce4a7d73f033a69a4c075311ff756f06a
Rebeka Dekany 1 year ago
parent
commit
971a5d9de4

+ 2 - 1
services/web/app/views/_mixins/bookmarkable_tabset.pug

@@ -1,7 +1,8 @@
 mixin bookmarkable-tabset-header(id, title, active)
-	li(role="presentation" class=(active ? 'active' : ''))
+	li(role="presentation")
 		a(
 			href='#' + id
+			class=(active ? 'active' : '')
 			aria-controls=id
 			role="tab"
 			data-toggle="tab"

+ 91 - 85
services/web/app/views/admin/index.pug

@@ -1,99 +1,105 @@
 extends ../layout-marketing
 include ../_mixins/bookmarkable_tabset
 
+block vars
+	- bootstrap5PageStatus = 'enabled' // One of 'disabled', 'enabled', and 'queryStringOnly'
+
 block content
 	.content.content-alt#main-content
 		.container
 			.row
-				.col-xs-12
+				.col-sm-12
 					.card
-						.page-header
-							h1 Admin Panel
-						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')
-									+bookmarkable-tabset-header('tpds', 'TPDS/Dropbox Management')
+						.card-body
+							.page-header
+								h1 Admin Panel
+							div(data-ol-bookmarkable-tabset)
+								.nav-tabs-container
+									ul.nav.nav-tabs.d-flex(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')
+											+bookmarkable-tabset-header('tpds', 'TPDS/Dropbox Management')
 
-							.tab-content
-								.tab-pane.active(
-									role="tabpanel"
-									id='system-messages'
-								)
-									each message in systemMessages
-										.alert.alert-info.row-spaced #{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-content
+										.tab-pane.active(
+											role="tabpanel"
+											id='system-messages'
+										)
+											each message in systemMessages
+												ul.system-messages
+													li.system-message.row-spaced #{message.content}
+											hr
+											form(method='post', action='/admin/messages')
+												input(name="_csrf", type="hidden", value=csrfToken)
+												.form-group
+													label.form-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-pane(
-									role="tabpanel"
-									id='open-sockets'
-								)
-									.row-spaced
-										ul
-											each agents, url in openSockets
-												li #{url} - total : #{agents.length}
-													ul
-														each agent in agents
-															li #{agent}
+										.tab-pane(
+											role="tabpanel"
+											id='open-sockets'
+										)
+											.row-spaced
+												ul
+													each agents, url in openSockets
+														li #{url} - total : #{agents.length}
+															ul
+																each agent in agents
+																	li #{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.
+										.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/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.
+												.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
+										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.form-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.form-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

+ 48 - 0
services/web/frontend/stylesheets/bootstrap-5/components/nav.scss

@@ -57,3 +57,51 @@
   --navbar-hamburger-submenu-item-hover-color: var(--navbar-link-color);
   --navbar-hamburger-submenu-item-hover-bg: var(--navbar-link-hover-bg);
 }
+
+.nav {
+  margin-bottom: 0;
+  padding-left: 0;
+  list-style: none;
+  display: block;
+
+  > li {
+    position: relative;
+    display: block;
+
+    > a {
+      position: relative;
+      display: block;
+      padding: var(--spacing-04) var(--spacing-06);
+
+      &:hover,
+      &:focus {
+        text-decoration: none;
+        background-color: var(--bg-info-01);
+        color: var(--white);
+      }
+    }
+
+    // Disabled state sets text to gray and nukes hover/tab effects
+    &.disabled > a {
+      color: var(--content-disabled);
+
+      &:hover,
+      &:focus {
+        color: var(--content-disabled);
+        text-decoration: none;
+        background-color: transparent;
+        cursor: not-allowed;
+      }
+    }
+  }
+
+  // Open dropdowns
+  .open > a {
+    &,
+    &:hover,
+    &:focus {
+      background-color: var(--bg-info-01);
+      border-color: var(--link-ui);
+    }
+  }
+}

+ 46 - 0
services/web/frontend/stylesheets/bootstrap-5/components/tabs.scss

@@ -78,3 +78,49 @@
 [data-ol-bookmarkable-tabset] .tab-pane {
   scroll-margin-top: 120px;
 }
+
+[data-ol-bookmarkable-tabset] {
+  .nav-tabs-container {
+    .nav-tabs {
+      gap: 8px;
+      flex-wrap: nowrap;
+
+      > li {
+        float: left;
+
+        // Make the list-items overlay the bottom border
+        margin-bottom: -1px;
+
+        // Actual tabs (as links)
+        > a {
+          color: var(--content-secondary);
+          border: 1px solid transparent;
+          border-radius: var(--border-radius-base) var(--border-radius-base) 0 0;
+          padding: var(--spacing-04);
+          text-decoration: none;
+
+          &:hover,
+          &:focus {
+            cursor: pointer;
+            background-color: var(--bg-light-secondary);
+          }
+        }
+
+        // Active state, and its :hover to override normal :hover
+        > a.active {
+          color: var(--content-primary);
+          background-color: var(--bg-light-primary);
+          border: 1px solid var(--border-divider);
+          border-bottom-color: transparent;
+          cursor: default;
+        }
+      }
+    }
+
+    .tab-content {
+      border: 1px solid #ddd;
+      border-top: none;
+      padding: var(--spacing-05);
+    }
+  }
+}

+ 0 - 48
services/web/frontend/stylesheets/bootstrap-5/pages/editor/left-menu.scss

@@ -189,54 +189,6 @@
   background-color: transparent;
 }
 
-.nav {
-  margin-bottom: 0;
-  padding-left: 0;
-  list-style: none;
-  display: block;
-
-  > li {
-    position: relative;
-    display: block;
-
-    > a {
-      position: relative;
-      display: block;
-      padding: var(--spacing-04) var(--spacing-06);
-
-      &:hover,
-      &:focus {
-        text-decoration: none;
-        background-color: var(--bg-info-01);
-        color: white;
-      }
-    }
-
-    // Disabled state sets text to gray and nukes hover/tab effects
-    &.disabled > a {
-      color: var(--content-disabled);
-
-      &:hover,
-      &:focus {
-        color: var(--content-disabled);
-        text-decoration: none;
-        background-color: transparent;
-        cursor: not-allowed;
-      }
-    }
-  }
-
-  // Open dropdowns
-  .open > a {
-    &,
-    &:hover,
-    &:focus {
-      background-color: var(--bg-info-01);
-      border-color: var(--link-ui);
-    }
-  }
-}
-
 .loading-spinner-container {
   display: flex;
   align-items: center;