ImportView.svelte raw

   1  <script>
   2      export let isLoggedIn = false;
   3      export let currentEffectiveRole = "";
   4      export let selectedFile = null;
   5      export let aclMode = "";
   6      export let importMessage = "";
   7  
   8      import { createEventDispatcher } from "svelte";
   9      const dispatch = createEventDispatcher();
  10  
  11      // When ACL is "none", allow access without login
  12      $: canImport = aclMode === "none" || (isLoggedIn && (currentEffectiveRole === "admin" || currentEffectiveRole === "owner"));
  13  
  14      function handleFileSelect(event) {
  15          dispatch("fileSelect", event);
  16      }
  17  
  18      function importEvents() {
  19          dispatch("importEvents");
  20      }
  21  
  22      function openLoginModal() {
  23          dispatch("openLoginModal");
  24      }
  25  </script>
  26  
  27  <div class="import-section">
  28      {#if canImport}
  29          <h3>Import Events</h3>
  30          <p>Upload a JSONL file to import events into the database.</p>
  31          <div class="recovery-controls-card">
  32              <input
  33                  type="file"
  34                  id="import-file"
  35                  accept=".jsonl,.txt"
  36                  on:change={handleFileSelect}
  37              />
  38              <div class="import-row">
  39                  <button
  40                      class="import-btn"
  41                      on:click={importEvents}
  42                      disabled={!selectedFile || importMessage === "Uploading..."}
  43                  >
  44                      Import Events
  45                  </button>
  46                  {#if importMessage}
  47                      <span class="import-message" class:uploading={importMessage === "Uploading..."} class:success={importMessage === "Upload complete"} class:error={importMessage.startsWith("Import failed") || importMessage.startsWith("Admin") || importMessage.startsWith("Please")}>{importMessage}</span>
  48                  {/if}
  49              </div>
  50          </div>
  51      {:else if isLoggedIn}
  52          <div class="permission-denied">
  53              <h3 class="recovery-header">Import Events</h3>
  54              <p class="recovery-description">
  55                  Admin or owner permission required for import functionality.
  56              </p>
  57          </div>
  58      {:else}
  59          <div class="login-prompt">
  60              <h3 class="recovery-header">Import Events</h3>
  61              <p class="recovery-description">
  62                  Please log in to access import functionality.
  63              </p>
  64              <button class="login-btn" on:click={openLoginModal}>Log In</button>
  65          </div>
  66      {/if}
  67  </div>
  68  
  69  <style>
  70      .import-section {
  71          background: transparent;
  72          padding: 1em;
  73          border-radius: 8px;
  74          margin-bottom: 1.5rem;
  75          width: 100%;
  76          max-width: 32em;
  77          box-sizing: border-box;
  78      }
  79  
  80      .import-section h3 {
  81          margin: 0 0 1rem 0;
  82          color: var(--text-color);
  83          font-size: 1.2rem;
  84          font-weight: 600;
  85      }
  86  
  87      .import-section p {
  88          margin: 0 0 1.5rem 0;
  89          color: var(--text-color);
  90          opacity: 0.8;
  91          line-height: 1.4;
  92      }
  93  
  94      .recovery-controls-card {
  95          background-color: var(--card-bg);
  96          padding: 1em;
  97          border: 0;
  98          display: flex;
  99          flex-direction: column;
 100          border-radius: 0.5em;
 101          gap: 1em;
 102      }
 103  
 104      #import-file {
 105          padding: 0.5em;
 106          border: 0;
 107          background: var(--input-bg);
 108          color: var(--input-text-color);
 109      }
 110  
 111      .import-btn {
 112          background-color: var(--primary);
 113          color: var(--text-color);
 114          border-radius: 0.5em;
 115          padding: 0.75em 1.5em;
 116          border: 0;
 117          cursor: pointer;
 118          font-weight: bold;
 119          font-size: 0.9em;
 120          transition: background-color 0.2s;
 121          align-self: flex-start;
 122      }
 123  
 124      .import-btn:hover:not(:disabled) {
 125          background-color: var(--accent-hover-color);
 126      }
 127  
 128      .import-btn:disabled {
 129          background-color: var(--secondary);
 130          cursor: not-allowed;
 131      }
 132  
 133      .import-row {
 134          display: flex;
 135          align-items: center;
 136          gap: 1em;
 137      }
 138  
 139      .import-message {
 140          font-size: 0.9em;
 141          padding: 0.25em 0.5em;
 142          border-radius: 0.25em;
 143      }
 144  
 145      .import-message.uploading {
 146          color: var(--primary);
 147      }
 148  
 149      .import-message.success {
 150          color: var(--success);
 151      }
 152  
 153      .import-message.error {
 154          color: var(--danger);
 155      }
 156  
 157      .permission-denied,
 158      .login-prompt {
 159          text-align: center;
 160          padding: 2em;
 161          background-color: var(--card-bg);
 162          border: 0;
 163      }
 164  
 165      .recovery-header {
 166          margin: 0 0 1rem 0;
 167          color: var(--text-color);
 168          font-size: 1.2rem;
 169          font-weight: 600;
 170      }
 171  
 172      .recovery-description {
 173          margin: 0 0 1.5rem 0;
 174          color: var(--text-color);
 175          line-height: 1.4;
 176      }
 177  
 178      .login-btn {
 179          background-color: var(--primary);
 180          color: var(--text-color);
 181          border: none;
 182          padding: 0.75em 1.5em;
 183          border: 0;
 184          cursor: pointer;
 185          font-weight: bold;
 186          font-size: 0.9em;
 187          transition: background-color 0.2s;
 188      }
 189  
 190      .login-btn:hover {
 191          background-color: var(--accent-hover-color);
 192      }
 193  </style>
 194