Skip to content

Commit

Permalink
Merge pull request #353 from PaperBoardOfficial/zip-upload-feature
Browse files Browse the repository at this point in the history
Added zip file upload feature
  • Loading branch information
yamadashy authored Feb 21, 2025
2 parents 2f0c679 + 4961bbc commit c79e58a
Show file tree
Hide file tree
Showing 17 changed files with 954 additions and 123 deletions.
2 changes: 2 additions & 0 deletions website/client/.vitepress/theme/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
--vp-c-brand-3: #c2410c;
--vp-c-brand-soft: rgba(249, 115, 22, 0.1);

--vp-c-danger: #f44336;

--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: linear-gradient(120deg, #f97316 30%, #ffb25c);

Expand Down
71 changes: 71 additions & 0 deletions website/client/components/PackButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<template>
<button
class="pack-button"
:disabled="!isValid || loading"
aria-label="Pack repository"
type="submit"
>
{{ loading ? 'Processing...' : 'Pack' }}
<svg v-if="!loading"
class="pack-button-icon"
width="20"
height="20"
viewBox="96.259 93.171 300 300"
>
<g transform="matrix(1.160932, 0, 0, 1.160932, 97.635941, 94.725143)">
<path
fill="currentColor"
d="M 128.03 -1.486 L 21.879 65.349 L 21.848 190.25 L 127.979 256.927 L 234.2 190.27 L 234.197 65.463 L 128.03 -1.486 Z M 208.832 70.323 L 127.984 121.129 L 47.173 70.323 L 128.144 19.57 L 208.832 70.323 Z M 39.669 86.367 L 119.188 136.415 L 119.255 230.529 L 39.637 180.386 L 39.669 86.367 Z M 136.896 230.506 L 136.887 136.575 L 216.469 86.192 L 216.417 180.46 L 136.896 230.506 Z M 136.622 230.849"
/>
</g>
</svg>
</button>
</template>

<script setup>
defineProps({
loading: Boolean,
isValid: Boolean,
});
</script>

<style scoped>
.pack-button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 12px 24px;
height: 50px;
width: 100%;
font-size: 16px;
font-weight: 500;
background: var(--vp-c-brand-1);
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
}
.pack-button:hover:not(:disabled) {
background: var(--vp-c-brand-2);
}
.pack-button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.pack-button-icon {
font-size: 20px;
line-height: 1;
}
@media (max-width: 768px) {
.pack-button {
width: 100%;
}
}
</style>
204 changes: 168 additions & 36 deletions website/client/components/TryIt.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,81 @@
<template>
<div class="container">
<form class="try-it-container" @submit.prevent="handleSubmit">
<div class="input-row">
<div class="tab-container">
<button
type="button"
:class="{ active: mode === 'url' }"
@click="setMode('url')"
>
URL Input
</button>
<button
type="button"
:class="{ active: mode === 'file' }"
@click="setMode('file')"
>
File Upload
</button>
</div>

<div class="input-field">
<TryItFileUpload
v-if="mode === 'file'"
@upload="handleFileUpload"
:loading="loading"
:show-button="false"
/>
<TryItUrlInput
v-else
v-model:url="url"
:loading="loading"
@keydown="handleKeydown"
:show-button="false"
/>
</div>

<div class="pack-button-wrapper">
<PackButton
:loading="loading"
:isValid="isSubmitValid"
/>
</div>
</div>

<TryItPackOptions
v-model:format="format"
v-model:include-patterns="includePatterns"
v-model:ignore-patterns="ignorePatterns"
v-model:file-summary="fileSummary"
v-model:directory-structure="directoryStructure"
v-model:remove-comments="removeComments"
v-model:remove-empty-lines="removeEmptyLines"
v-model:show-line-numbers="showLineNumbers"
v-model:output-parsable="outputParsable"
/>

<div v-if="hasExecuted">
<TryItResultViewer
:result="result"
:loading="loading"
:error="error"
/>
</div>
</form>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { computed, ref } from 'vue';
import PackButton from './PackButton.vue';
import TryItFileUpload from './TryItFileUpload.vue';
import TryItPackOptions from './TryItPackOptions.vue';
import TryItResultViewer from './TryItResultViewer.vue';
import TryItUrlInput from './TryItUrlInput.vue';
import type { PackResult } from './api/client';
import { handlePackRequest } from './utils/requestHandlers';
import { isValidRemoteValue } from './utils/validation';
// Form input states
const url = ref('');
Expand All @@ -23,12 +94,32 @@ const loading = ref(false);
const error = ref<string | null>(null);
const result = ref<PackResult | null>(null);
const hasExecuted = ref(false);
const mode = ref<'url' | 'file'>('url');
const uploadedFile = ref<File | null>(null);
// Compute if the current mode's input is valid for submission
const isSubmitValid = computed(() => {
switch (mode.value) {
case 'url':
return !!url.value && isValidRemoteValue(url.value.trim());
case 'file':
return !!uploadedFile.value;
default:
return false;
}
});
// Explicitly set the mode and handle related state changes
function setMode(newMode: 'url' | 'file') {
mode.value = newMode;
}
const TIMEOUT_MS = 30_000;
let requestController: AbortController | null = null;
async function handleSubmit() {
if (!url.value) return;
// Check if current mode has valid input
if (!isSubmitValid.value) return;
// Cancel any pending request
if (requestController) {
Expand All @@ -49,7 +140,7 @@ async function handleSubmit() {
}, TIMEOUT_MS);
await handlePackRequest(
url.value,
mode.value === 'url' ? url.value : '',
format.value,
{
removeComments: removeComments.value,
Expand All @@ -69,6 +160,7 @@ async function handleSubmit() {
error.value = errorMessage;
},
signal: requestController.signal,
file: mode.value === 'file' ? uploadedFile.value || undefined : undefined,
},
);
Expand All @@ -79,43 +171,15 @@ async function handleSubmit() {
}
function handleKeydown(event: KeyboardEvent) {
if (event.key === 'Enter' && url.value && !loading.value) {
if (event.key === 'Enter' && mode.value === 'url' && isSubmitValid.value && !loading.value) {
handleSubmit();
}
}
</script>

<template>
<div class="container">
<form class="try-it-container" @submit.prevent="handleSubmit">
<TryItUrlInput
v-model:url="url"
:loading="loading"
@keydown="handleKeydown"
/>

<TryItPackOptions
v-model:format="format"
v-model:include-patterns="includePatterns"
v-model:ignore-patterns="ignorePatterns"
v-model:file-summary="fileSummary"
v-model:directory-structure="directoryStructure"
v-model:remove-comments="removeComments"
v-model:remove-empty-lines="removeEmptyLines"
v-model:show-line-numbers="showLineNumbers"
v-model:output-parsable="outputParsable"
/>
<div v-if="hasExecuted">
<TryItResultViewer
:result="result"
:loading="loading"
:error="error"
/>
</div>
</form>
</div>
</template>
function handleFileUpload(file: File) {
uploadedFile.value = file;
}
</script>

<style scoped>
.container {
Expand All @@ -130,4 +194,72 @@ function handleKeydown(event: KeyboardEvent) {
border-radius: 12px;
padding: 24px;
}
.input-row {
display: grid;
grid-template-columns: auto 1fr auto;
gap: 12px;
margin-bottom: 24px;
align-items: start;
}
.tab-container {
display: flex;
flex-direction: row;
width: 240px;
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--vp-c-border);
}
.tab-container button {
flex: 1;
height: 48px;
padding: 0 16px;
background: white;
cursor: pointer;
font-size: 16px;
white-space: nowrap;
transition: all 0.2s;
}
.tab-container button:first-child {
border-radius: 8px 0 0 8px;
border-right: none;
}
.tab-container button:last-child {
border-radius: 0 8px 8px 0;
}
.tab-container button.active {
background: var(--vp-c-brand-1);
color: white;
}
.input-field {
align-self: start;
}
.pack-button-wrapper {
display: flex;
align-items: stretch;
align-self: start;
}
/* Responsive adjustments */
@media (max-width: 768px) {
.input-row {
grid-template-columns: 1fr;
gap: 12px;
}
.tab-container {
width: 100%;
}
.pack-button-wrapper {
width: 100%;
}
}
</style>
Loading

0 comments on commit c79e58a

Please sign in to comment.