Skip to content

File Upload Configuration

  • File: src/pages/private/admin/uploads/index.svelte

Overview

The File Upload Configuration page allows administrators to manage file upload settings, including file extensions, size limits, and file types. It provides an interface for creating, editing, and deleting upload configurations.

Data Structures

Upload Configuration Interface

ts
interface UploadConfig {
  extension: string;
  maxSize: string;
  fileSize: string;
  type: string;
  id?: string;
}

Core Functions

1. Upload Configuration Management

svelte
// Create upload configuration
async function createUpload(upload) {
  const query = `
    mutation SendData ($input: [FileUploadConfigInput!]!){
      saveFileUploadConfig(
        command: {input: $input}
      ){
        success, message, code
      }
    }
  `;

  const { data, error } = await mutation<any>(query, { input: upload });
  if (error) {
    showError(error.message);
  }
  return data;
}

Event Handlers

1. Form Operations

svelte
// Handle form submission
function handleEntry({ detail }: CustomEvent) {
  uploads = [{
    ...detail,
    id: uniqueId(detail.extension)
  }, ...uploads];
  closeForm();
}

// Close form modal
function closeForm() {
  showModal = false;
  activeUpload = null;
  setEdit = false;
}

// Initialize edit mode
function initEdit(role) {
  activeUpload = role;
  setEdit = true;
  showModal = true;
}

// Initialize delete operation
function initDelete(role, index) {
  uploads = uploads.filter((_, i) => i !== index);
}

2. Save Operations

svelte
async function handleSubmit() {
  const data = uploads.map((x) => ({
    extension: x.extension,
    maxSize: `${x.maxSize}${x.fileSize}`,
    type: x.type,
  }));

  await toast.promise(createUpload(data), {
    loading: "Uploading files...",
    success: (ret: any) => {
      if (!ret?.saveFileUploadConfig?.success) {
        return ret.message || "Upload failed";
      }
      return ret?.saveFileUploadConfig?.message || "Record added";
    },
    error: (error: any) => {
      const errorMessage = error?.message || error;
      return `Error: ${errorMessage}`;
    },
  });
}

UI Implementation

1. Main Layout

svelte
<div class="min-w-full px-4 sm:px-6 lg:px-8">
  <!-- Header -->
  <div class="mb-2 sm:flex sm:items-center">
    <h3 class="text-lg leading-6 font-medium text-indigo-900">Uploads</h3>
    <button
      on:click={(_) => (showModal = true)}
      class="inline-flex items-center justify-center rounded-md border border-transparent bg-[#2d4e8c] px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-[#2d4e8c] focus:outline-none sm:w-auto"
    >
      Add Config
    </button>
  </div>

  <!-- Upload Configurations Table -->
  <div class="pt-4 flex flex-col sm:border-t sm:border-gray-200">
    {#if busy}
      <div class="flex-grow grid place-content-center my-3 py-3">
        <Chasing />
      </div>
    {:else if !uploads.length}
      <div class="grid place-content-center">
        <div class="alert alert-info max-w-sm mt-3 ml-3">
          There are no uploads configs to show
        </div>
      </div>
    {:else}
      <table class="min-w-full divide-y divide-gray-300">
        <!-- Table Header -->
        <thead class="bg-gray-50">
          <tr>
            <th>#</th>
            <th>Extension</th>
            <th>Size</th>
            <th>Type</th>
            <th>Actions</th>
          </tr>
        </thead>

        <!-- Table Body -->
        <tbody class="divide-y divide-gray-200 bg-white">
          {#each uploads as role, i}
            <tr>
              <td>{i + 1}</td>
              <td>{role.extension}</td>
              <td>{`${role.maxSize} ${role.fileSize}`}</td>
              <td>{role.type}</td>
              <td>
                <!-- Action Buttons -->
                <span use:tip={{ content: "Edit Upload" }}>
                  <Icon class="h-4 w-4" src={PencilAlt} />
                </span>
                <span use:tip={{ content: "Delete Upload" }}>
                  <Icon class="h-4 w-4" src={Trash} />
                </span>
              </td>
            </tr>
          {/each}
        </tbody>
      </table>

      <!-- Save Button -->
      <div class="flex justify-end pr-8">
        <button
          on:click={handleSubmit}
          class="bg-[#7ab800] hover:bg-[#8cac4c] focus:ring-indigo-500 w-full inline-flex justify-center rounded-md px-4 py-2 text-base font-medium text-white border-transparent border shadow-sm sm:w-auto sm:text-sm mt-3"
        >
          Save Entries
        </button>
      </div>
    {/if}
  </div>
</div>

2. Modal Implementation

svelte
{#if showModal}
  <SideModal>
    <Form
      on:cancel={closeForm}
      on:submit={handleEntry}
      data={activeUpload}
      edit={setEdit}
    />
  </SideModal>
{/if}

Initialization

svelte
onMount(() => {
  // Check admin permissions
  if (!$userInfo?.isAdmin) {
    $goto("/private/dashboard");
    return;
  }

  // Load existing configurations
  if ($userInfo?.tenant.fileUploadConfig?.length) {
    uploads = $userInfo.tenant.fileUploadConfig.map((x) => {
      const maxSize = x.maxSize;
      const fileSize = maxSize.slice(-2);
      const maxSizeValue = maxSize.slice(0, -2);

      return {
        extension: x.extension,
        type: x.type,
        fileSize,
        maxSize: maxSizeValue,
      };
    });
  }
});

Released under the MIT License.