Просмотр исходного кода

Merge pull request #20880 from overleaf/ii-bs5-submit-modal

[web] BS5 submit modal

GitOrigin-RevId: 1c66b3874844d9bdbe129acd18480af6e6e0ef6e
Rebeka Dekany 1 год назад
Родитель
Сommit
d71f82b1fa

+ 8 - 4
services/web/frontend/js/features/ui/components/ol/ol-card.tsx

@@ -1,16 +1,20 @@
-import { Card, CardBody } from 'react-bootstrap-5'
+import { Card, CardBody, CardProps } from 'react-bootstrap-5'
 import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
 import { FC } from 'react'
 
 // This wraps the Bootstrap 5 Card component but is restricted to the very
 // basic way we're using it, which is as a container for page content. The
 // Bootstrap 3 equivalent in our codebase is a div with class "card"
-const OLCard: FC = ({ children }) => {
+const OLCard: FC<CardProps> = ({ children, ...rest }) => {
   return (
     <BootstrapVersionSwitcher
-      bs3={<div className="card">{children}</div>}
+      bs3={
+        <div className="card" {...rest}>
+          {children}
+        </div>
+      }
       bs5={
-        <Card>
+        <Card {...rest}>
           <CardBody>{children}</CardBody>
         </Card>
       }

+ 1 - 0
services/web/frontend/js/features/ui/components/ol/ol-form-label.tsx

@@ -13,6 +13,7 @@ function OLFormLabel(props: OLFormLabelProps) {
     children: rest.children,
     htmlFor: rest.htmlFor,
     srOnly: rest.visuallyHidden,
+    className: rest.className,
     ...bs3Props,
   }
 

+ 41 - 30
services/web/frontend/js/features/ui/components/ol/ol-form-select.tsx

@@ -1,3 +1,4 @@
+import { forwardRef } from 'react'
 import { Form, FormSelectProps } from 'react-bootstrap-5'
 import {
   FormControl as BS3FormControl,
@@ -10,38 +11,48 @@ type OLFormSelectProps = FormSelectProps & {
   bs3Props?: Record<string, unknown>
 }
 
-function OLFormSelect(props: OLFormSelectProps) {
-  const { bs3Props, ...bs5Props } = props
+const OLFormSelect = forwardRef<HTMLSelectElement, OLFormSelectProps>(
+  (props, ref) => {
+    const { bs3Props, ...bs5Props } = props
 
-  const bs3FormSelectProps: BS3FormControlProps = {
-    children: bs5Props.children,
-    bsSize: bs5Props.size,
-    name: bs5Props.name,
-    value: bs5Props.value,
-    defaultValue: bs5Props.defaultValue,
-    disabled: bs5Props.disabled,
-    onChange: bs5Props.onChange as BS3FormControlProps['onChange'],
-    required: bs5Props.required,
-    placeholder: bs5Props.placeholder,
-    className: bs5Props.className,
-    ...bs3Props,
-  }
+    const bs3FormSelectProps: BS3FormControlProps = {
+      children: bs5Props.children,
+      bsSize: bs5Props.size,
+      name: bs5Props.name,
+      value: bs5Props.value,
+      defaultValue: bs5Props.defaultValue,
+      disabled: bs5Props.disabled,
+      onChange: bs5Props.onChange as BS3FormControlProps['onChange'],
+      required: bs5Props.required,
+      placeholder: bs5Props.placeholder,
+      className: bs5Props.className,
+      inputRef: (inputElement: HTMLInputElement) => {
+        if (typeof ref === 'function') {
+          ref(inputElement as unknown as HTMLSelectElement)
+        } else if (ref) {
+          ref.current = inputElement as unknown as HTMLSelectElement
+        }
+      },
+      ...bs3Props,
+    }
 
-  // Get all `aria-*` and `data-*` attributes
-  const extraProps = getAriaAndDataProps(bs5Props)
+    // Get all `aria-*` and `data-*` attributes
+    const extraProps = getAriaAndDataProps(bs5Props)
 
-  return (
-    <BootstrapVersionSwitcher
-      bs3={
-        <BS3FormControl
-          componentClass="select"
-          {...bs3FormSelectProps}
-          {...extraProps}
-        />
-      }
-      bs5={<Form.Select {...bs5Props} />}
-    />
-  )
-}
+    return (
+      <BootstrapVersionSwitcher
+        bs3={
+          <BS3FormControl
+            componentClass="select"
+            {...bs3FormSelectProps}
+            {...extraProps}
+          />
+        }
+        bs5={<Form.Select ref={ref} {...bs5Props} />}
+      />
+    )
+  }
+)
+OLFormSelect.displayName = 'OLFormSelect'
 
 export default OLFormSelect

+ 2 - 1
services/web/frontend/js/shared/components/loading-spinner.tsx

@@ -3,6 +3,7 @@ import Icon from './icon'
 import { useEffect, useState } from 'react'
 import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
 import { Spinner } from 'react-bootstrap-5'
+import { setTimeout } from '@/utils/window'
 import classNames from 'classnames'
 
 function LoadingSpinner({
@@ -21,7 +22,7 @@ function LoadingSpinner({
   const [show, setShow] = useState(false)
 
   useEffect(() => {
-    const timer = window.setTimeout(() => {
+    const timer = setTimeout(() => {
       setShow(true)
     }, delay)
 

+ 3 - 0
services/web/frontend/js/utils/window.ts

@@ -0,0 +1,3 @@
+// Allows easy mocking of `window` methods in tests
+
+export const setTimeout = window.setTimeout

+ 8 - 46
services/web/frontend/stylesheets/app/editor/publish-modal.less

@@ -1,46 +1,10 @@
 .modal-body-publish {
-  @label-column-width: 10em;
-  @control-left-margin: 1em;
-  .form-control-box {
-    margin-bottom: 1.5ex;
-    margin-left: @control-left-margin;
-    label {
-      display: inline-block;
-      width: @label-column-width;
-      vertical-align: baseline;
-    }
-    label.checkbox-label {
-      width: auto;
-    }
-    .form-control {
-      display: inline-block;
-      width: 60%;
-    }
-    input[type='checkbox'] {
-      margin-right: 0.5em;
-    }
-    textarea {
-      vertical-align: baseline;
-    }
-    select {
-      padding-top: 1ex;
-      padding-bottom: 1ex;
-      padding-left: 1em;
-      padding-right: 1em;
-    }
-    option {
-      margin-left: -4px;
-    }
-    a.help {
-      margin-left: 0.6em;
-    }
+  input[type='checkbox'] {
+    margin-top: 6px;
   }
-  .no-label {
-    margin-left: @label-column-width + @control-left-margin;
-  }
-  #search-input-container {
-    overflow: hidden;
-    margin: 5px 0 10px;
+  .gallery-export-license {
+    display: flex;
+    align-items: center;
   }
   .table-content-name {
     width: 100%;
@@ -70,6 +34,7 @@
   .button-as-link {
     color: green;
     text-transform: none;
+    text-decoration: none;
     background: none;
     padding: 0;
     border: none;
@@ -101,12 +66,10 @@
     border-radius: 9px;
   }
   .content-as-table {
-    .table-content,
-    .table-content > * {
-      display: table;
+    .table-content-main {
+      display: flex;
     }
     .table-content-icon {
-      float: left;
       height: 100px;
       width: 106px;
       display: flex;
@@ -118,7 +81,6 @@
       }
     }
     .table-content-text {
-      float: right;
       width: calc(~'100% - 106px');
       vertical-align: top;
       padding-left: 15px;

+ 1 - 0
services/web/frontend/stylesheets/bootstrap-5/pages/all.scss

@@ -18,6 +18,7 @@
 @import 'subscription';
 @import 'editor/pdf';
 @import 'editor/compile-button';
+@import 'editor/publish-modal';
 @import 'editor/share';
 @import 'editor/tags-input';
 @import 'website-redesign';

+ 84 - 0
services/web/frontend/stylesheets/bootstrap-5/pages/editor/publish-modal.scss

@@ -0,0 +1,84 @@
+.modal-body-publish {
+  .gallery-export-license {
+    display: flex;
+    align-items: center;
+  }
+
+  .table-content-name {
+    width: 100%;
+    margin-bottom: var(--spacing-05);
+    font-weight: 300;
+  }
+
+  .table-content-category {
+    float: right;
+    font-weight: 300;
+    text-align: right;
+    font-style: italic;
+    width: 30%;
+    text-transform: capitalize;
+  }
+
+  .table-content-category ~ .table-content-name {
+    width: 70%;
+    display: inline-block;
+  }
+
+  .affix-content-title {
+    color: var(--neutral-40);
+    font-size: var(--spacing-07);
+    padding-left: var(--spacing-05);
+  }
+
+  .affix-subcontent {
+    margin: var(--spacing-03) 0 var(--spacing-11);
+  }
+
+  .card {
+    margin-top: calc(var(--line-height-03) / 2);
+    border: 1px solid var(--neutral-30);
+    border-radius: var(--border-radius-medium);
+
+    .card-body {
+      padding: calc(var(--line-height-03) / 2);
+    }
+  }
+
+  .content-as-table {
+    .table-content-main {
+      display: flex;
+    }
+
+    .table-content-icon {
+      height: 100px;
+      width: 106px;
+      display: flex;
+      align-items: flex-start;
+      overflow: hidden;
+
+      * {
+        border: 1px solid var(--neutral-10);
+        width: 100%;
+      }
+    }
+
+    .table-content-text {
+      width: calc(100% - 106px);
+      vertical-align: top;
+      padding-left: 15px;
+    }
+
+    .table-content-slogan {
+      height: 100px;
+      overflow: hidden;
+    }
+
+    .table-content-link {
+      padding-top: var(--spacing-05);
+
+      .btn {
+        white-space: normal;
+      }
+    }
+  }
+}