Browse Source

Update layout and styling

arvid-e 4 months ago
parent
commit
52aea42f81

+ 98 - 122
apps/app/src/client/components/Admin/MarkdownSetting/ContentDispositionSettings.tsx

@@ -2,22 +2,18 @@ import React, {
   useState, useCallback, useEffect, useMemo,
 } from 'react';
 
-// Use the refactored hook and its exported type
 import { useContentDisposition, type ContentDispositionSettings } from '../../../services/AdminContentDispositionSettings';
+import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
+
 
-/**
- * Helper function to ensure the mime type is normalized / clean before use.
- */
 const normalizeMimeType = (mimeType: string): string => mimeType.trim().toLowerCase();
 
-// Helper to remove a mimeType from an array
 const removeMimeTypeFromArray = (array: string[], mimeType: string): string[] => (
   array.filter(m => m !== mimeType)
 );
 
 const ContentDispositionSettings: React.FC = () => {
 
-  // 1. Updated destructuring from the refactored hook
   const {
     currentSettings,
     isLoading,
@@ -25,14 +21,12 @@ const ContentDispositionSettings: React.FC = () => {
     updateSettings,
   } = useContentDisposition();
 
-  // 2. State for pending changes and input
   const [pendingSettings, setPendingSettings] = useState<ContentDispositionSettings | null>(null);
   const [currentInput, setCurrentInput] = useState<string>('');
   const [error, setError] = useState<string | null>(null);
 
   useEffect(() => {
     if (currentSettings) {
-      // Deep copy to prevent mutating the original settings object
       setPendingSettings({
         inlineMimeTypes: [...currentSettings.inlineMimeTypes],
         attachmentMimeTypes: [...currentSettings.attachmentMimeTypes],
@@ -53,7 +47,6 @@ const ContentDispositionSettings: React.FC = () => {
   }, [currentSettings, pendingSettings]);
 
 
-  // 3. Handlers for setting (adding to pending state)
   const handleSetMimeType = useCallback((disposition: 'inline' | 'attachment') => {
     const mimeType = normalizeMimeType(currentInput);
     if (!mimeType) return;
@@ -65,13 +58,13 @@ const ContentDispositionSettings: React.FC = () => {
       const newSettings = { ...prev };
       const otherDisposition = disposition === 'inline' ? 'attachment' : 'inline';
 
-      // 1. Add to the target list (if not already present)
+      // Add to the target list (if not already present)
       const targetKey = `${disposition}MimeTypes` as keyof ContentDispositionSettings;
       if (!newSettings[targetKey].includes(mimeType)) {
         newSettings[targetKey] = [...newSettings[targetKey], mimeType];
       }
 
-      // 2. Remove from the other list
+      // Remove from the other list
       const otherKey = `${otherDisposition}MimeTypes` as keyof ContentDispositionSettings;
       newSettings[otherKey] = removeMimeTypeFromArray(newSettings[otherKey], mimeType);
 
@@ -96,20 +89,7 @@ const ContentDispositionSettings: React.FC = () => {
     });
   }, []);
 
-  // Handler for resetting to the last saved settings
-  const handleReset = useCallback(() => {
-    setError(null);
-    if (currentSettings) {
-      // Revert pending changes to the last fetched/saved state
-      setPendingSettings({
-        inlineMimeTypes: [...currentSettings.inlineMimeTypes],
-        attachmentMimeTypes: [...currentSettings.attachmentMimeTypes],
-      });
-    }
-  }, [currentSettings]);
-
-
-  // 4. Handler for updating (saving to server)
+  // Handler for updating pending change
   const handleUpdate = useCallback(async(): Promise<void> => {
     if (!pendingSettings || !hasPendingChanges || isUpdating) return;
 
@@ -120,7 +100,6 @@ const ContentDispositionSettings: React.FC = () => {
     catch (err) {
       const errorMessage = (err instanceof Error) ? err.message : 'An unknown error occurred during update.';
       setError(`Failed to update settings: ${errorMessage}`);
-      console.error('Failed to update settings:', err);
     }
   }, [pendingSettings, hasPendingChanges, isUpdating, updateSettings]);
 
@@ -131,112 +110,109 @@ const ContentDispositionSettings: React.FC = () => {
   const renderInlineMimeTypes = displaySettings.inlineMimeTypes;
   const renderAttachmentMimeTypes = displaySettings.attachmentMimeTypes;
 
-  // 5. Render logic
   return (
-    <div>
-      <h2>Content-Disposition Mime Type Settings ⚙️</h2>
-
-      {/* Input and Add Buttons */}
-      <div>
-        <input
-          type="text"
-          value={currentInput}
-          onChange={(e: React.ChangeEvent<HTMLInputElement>) => setCurrentInput(e.target.value)}
-          placeholder="e.g., image/png"
-        />
-        <button
-          type="button"
-          onClick={handleSetInline}
-          disabled={!currentInput.trim() || isUpdating}
-        >
-          Add Inline
-        </button>
-        <button
-          type="button"
-          onClick={handleSetAttachment}
-          disabled={!currentInput.trim() || isUpdating}
-        >
-          Add Attachment
-        </button>
-      </div>
-
-      <p style={{ fontSize: '12px', color: '#666' }}>
-        Note: Adding a mime type will **automatically remove it** from the other list if it exists there.
-      </p>
-
-      {/* Error Display */}
-      {error && (
-        <div>
-          **Error:** {error}
-        </div>
-      )}
-
-      {/* Update and Reset Buttons */}
-      <div style={{ marginBottom: '20px', display: 'flex', gap: '10px' }}>
-        <button
-          type="button"
-          onClick={handleUpdate}
-          disabled={!hasPendingChanges || isUpdating}
-        >
-          {isUpdating ? 'Updating...' : 'Update Settings'}
-        </button>
-        <button
-          type="button"
-          onClick={handleReset}
-          disabled={!hasPendingChanges || isUpdating}
-        >
-          Reset Changes
-        </button>
-      </div>
-
-
-      <hr />
-
-      <div style={{ display: 'flex', justifyContent: 'space-between' }}>
-
-        {/* INLINE List */}
-        <div>
-          <h3>Inline Mime Types (Viewable)</h3>
-          <ul>
-            {renderInlineMimeTypes.length === 0 && <li>No inline mime types set.</li>}
-            {renderInlineMimeTypes.map((mimeType: string) => (
-              <li
-                key={mimeType}
-              >
-                {mimeType}
+    <div className="row">
+      <div className="col-12">
+        <h2 className="pb-2">Content-Disposition Mime Type Settings</h2>
+
+        {/* INPUT SECTION */}
+        <div className="card shadow-sm mb-4">
+          <div className="card-body">
+            <div className="form-group">
+              <label className="form-label fw-bold">Add New Mime Type</label>
+              <div className="d-flex align-items-center gap-2">
+                <input
+                  type="text"
+                  className="form-control"
+                  value={currentInput}
+                  onChange={e => setCurrentInput(e.target.value)}
+                  placeholder="e.g., image/png"
+                />
                 <button
+                  className="btn btn-primary px-3"
                   type="button"
-                  onClick={() => handleRemove(mimeType, 'inline')}
-                  disabled={isUpdating}
+                  onClick={handleSetInline}
+                  disabled={!currentInput.trim() || isUpdating}
                 >
-                  Remove
+                  Inline
                 </button>
-              </li>
-            ))}
-          </ul>
-        </div>
-
-        {/* ATTACHMENT List */}
-        <div>
-          <h3>Attachment Mime Types (Forces Download)</h3>
-          <ul>
-            {renderAttachmentMimeTypes.length === 0 && <li>No attachment mime types set.</li>}
-            {renderAttachmentMimeTypes.map((mimeType: string) => (
-              <li
-                key={mimeType}
-              >
-                {mimeType}
                 <button
+                  className="btn btn-primary text-white px-3"
                   type="button"
-                  onClick={() => handleRemove(mimeType, 'attachment')}
-                  disabled={isUpdating}
+                  onClick={handleSetAttachment}
+                  disabled={!currentInput.trim() || isUpdating}
                 >
-                  Remove
+                  Attachment
                 </button>
-              </li>
-            ))}
-          </ul>
+              </div>
+              <small className="form-text text-muted mt-2 d-block">
+                Note: Adding a mime type will <strong>automatically remove it</strong> from the other list.
+              </small>
+            </div>
+          </div>
+        </div>
+
+        {error && (
+          <div className="alert alert-danger">{error}</div>
+        )}
+
+        <div className="row">
+          {/* INLINE LIST COLUMN */}
+          <div className="col-md-6 col-sm-12 align-self-start">
+            <div className="card">
+              <div className="card-header"><span className="fw-bold">Inline Mime Types</span></div>
+              <div className="card-body">
+                <ul className="list-group list-group-flush">
+                  {renderInlineMimeTypes.length === 0 && <li className="list-group-item text-muted">No inline types set.</li>}
+                  {renderInlineMimeTypes.map((mimeType: string) => (
+                    <li key={mimeType} className="list-group-item d-flex justify-content-between align-items-center">
+                      <code>{mimeType}</code>
+                      <button
+                        type="button" // Fixes the lint error
+                        className="btn btn-sm btn-outline-danger"
+                        onClick={() => handleRemove(mimeType, 'inline')}
+                        disabled={isUpdating}
+                      >
+                        Remove
+                      </button>
+                    </li>
+                  ))}
+                </ul>
+              </div>
+            </div>
+          </div>
+
+          {/* ATTACHMENT LIST COLUMN */}
+          <div className="col-md-6 col-sm-12 align-self-start">
+            <div className="card">
+              <div className="card-header"><span className="fw-bold">Attachment Mime Types</span></div>
+              <div className="card-body">
+                <ul className="list-group list-group-flush">
+                  {renderAttachmentMimeTypes.length === 0 && <li className="list-group-item text-muted">No attachment types set.</li>}
+                  {renderAttachmentMimeTypes.map((mimeType: string) => (
+                    <li key={mimeType} className="list-group-item d-flex justify-content-between align-items-center">
+                      <code>{mimeType}</code>
+                      <button
+                        type="button"
+                        className="btn btn-sm btn-outline-danger"
+                        onClick={() => handleRemove(mimeType, 'attachment')}
+                        disabled={isUpdating}
+                      >
+                        Remove
+                      </button>
+                    </li>
+                  ))}
+                </ul>
+              </div>
+            </div>
+          </div>
+
         </div>
+
+        <AdminUpdateButtonRow
+          onClick={handleUpdate}
+          disabled={!hasPendingChanges || isUpdating}
+        />
       </div>
     </div>
   );