Skip to content

Commit

Permalink
Merge pull request #38 from radek00/landing-page
Browse files Browse the repository at this point in the history
Landing page
  • Loading branch information
radek00 authored Nov 5, 2023
2 parents 6e3f2a8 + e3b6961 commit 48dc822
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 120 deletions.
20 changes: 20 additions & 0 deletions SecureSend/ClientApp/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,26 @@
<title>Vite App</title>
</head>
<body class="bg-gray-900 font-mono text-white w-screen">
<header class="text-slate-300">
<a href="/" class="flex items-center gap-2 pt-4 pl-4 w-fit">
<svg
style="width: 60px; height: 60px"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 20 16"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="0.9"
d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2"
/>
</svg>
<h1 class="text-2xl">SecureSend</h1>
</a>
</header>
<div class="flex justify-center h-screen items-center" id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
Expand Down
18 changes: 17 additions & 1 deletion SecureSend/ClientApp/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,21 @@ import { RouterView } from "vue-router";
id="alert-container"
class="absolute z-50 h-fit top-1 left-1 flex flex-col"
></div>
<RouterView />
<RouterView v-slot="{ Component, route }">
<transition name="fade" mode="out-in">
<component :is="Component" :key="route.path"></component>
</transition>
</RouterView>
</template>

<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
2 changes: 1 addition & 1 deletion SecureSend/ClientApp/src/components/ConfirmModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defineEmits(["closeClick"]);
<div
tabindex="-1"
aria-hidden="true"
class="absolute z-40 h-screen w-screen flex items-center justify-center bg-gray-900/50"
class="backdrop-blur fixed top-0 bottom-1/2 left-0 z-40 h-screen w-screen flex items-center justify-center bg-gray-900/50"
>
<div class="relative w-full max-w-2xl max-h-full">
<!-- Modal content -->
Expand Down
26 changes: 10 additions & 16 deletions SecureSend/ClientApp/src/components/FileUploadForm/FormStepper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,32 @@
'text-blue-500 after:border-blue-800 ': step === 0,
'after:border-4 after:inline-block after:border-gray-700 ': step !== 0,
}"
class="flex w-full items-center after:content-[''] after:w-full after:h-1 after:border-b after:border-4 after:inline-block after:transition-background-color after:linear after:duration-1000"
class="flex w-full items-center after:content-[''] after:w-full after:h-1 after:border-b after:border-4 after:inline-block after:transition after:linear after:duration-1000"
>
<span
class="flex items-center justify-center w-10 h-10 rounded-full lg:h-12 lg:w-12 shrink-0"
:class="{
'bg-blue-800 transition-background-color linear duration-1000 ':
step === 0,
'bg-gray-700 transition-background-color linear duration-1000':
step !== 0,
'bg-blue-800': step === 0,
'bg-gray-700': step !== 0,
}"
>
<PasswordIcon></PasswordIcon>
</span>
</li>
<li
:class="{
'text-blue-600 after:border-blue-800 transition-background-color linear duration-1000':
'text-blue-600 after:border-blue-800 transition linear duration-1000':
step === 1,
'after:border-4 after:inline-block after:border-gray-700 transition-background-color linear duration-1000':
'after:border-4 after:inline-block after:border-gray-700 transition linear duration-1000':
step !== 1,
}"
class="flex w-full items-center after:content-[''] after:w-full after:h-1 after:border-b after:border-4 after:inline-block after:transition-background-color after:linear after:duration-1000"
class="flex w-full items-center after:content-[''] after:w-full after:h-1 after:border-b after:border-4 after:inline-block after:transition after:linear after:duration-1000"
>
<span
class="flex items-center justify-center w-10 h-10 rounded-full lg:h-12 lg:w-12 shrink-0"
:class="{
'bg-blue-800 transition-background-color linear duration-1000':
step === 1,
'bg-gray-700 transition-background-color linear duration-1000':
step !== 1,
'bg-blue-800': step === 1,
'bg-gray-700': step !== 1,
}"
>
<CalendarIcon></CalendarIcon>
Expand All @@ -44,10 +40,8 @@
<span
class="flex items-center justify-center w-10 h-10 rounded-full lg:h-12 lg:w-12 shrink-0"
:class="{
'bg-blue-800 transition-background-color linear duration-1000':
step === 2,
'bg-gray-700 transition-background-color linear duration-1000':
step !== 2,
'bg-blue-800': step === 2,
'bg-gray-700': step !== 2,
}"
>
<UploadIconStep></UploadIconStep>
Expand Down
6 changes: 6 additions & 0 deletions SecureSend/ClientApp/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ import { createRouter, createWebHistory } from "vue-router";
const FileUploadView = () => import("@/views/FileUploadView.vue");
const FileDownloadView = () => import("@/views/FileDownloadView.vue");
const ErrorPageView = () => import("@/views/ErrorPageView.vue");
const LandingView = () => import("@/views/LandingView.vue");

const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: "/",
name: "home",
component: LandingView,
},
{
path: "/upload",
name: "upload",
component: FileUploadView,
},
{
Expand Down
204 changes: 102 additions & 102 deletions SecureSend/ClientApp/src/views/FileUploadView.vue
Original file line number Diff line number Diff line change
@@ -1,112 +1,111 @@
<template>
<form
@submit="onSubmit"
class="w-11/12 lg:w-6/12 flex flex-col justify-between gap-4 h-11/12 p-6 border rounded-lg shadow bg-gray-800 border-gray-800"
<div
class="w-11/12 lg:w-6/12 h-11/12 p-6 border rounded-lg shadow bg-gray-800 border-gray-800"
>
<FormStepper class="px-[10px]" :step="step"></FormStepper>
<div
class="flex overflow-hidden items-center h-[150px] transition-height duration-500"
:class="{ 'h-[100px]': step !== 2, 'h-[300px]': step === 2 }"
>
<div
class="w-full shrink-0 transition-transform duration-700 px-[10px]"
:style="{ transform }"
>
<SchemaInput
name="password"
type="password"
label="Encryption password"
:disabled="!values.isPasswordRequired"
></SchemaInput>
<CheckboxSchemaInput
name="isPasswordRequired"
:checked-value="true"
label="Password required"
></CheckboxSchemaInput>
</div>
<div
class="w-full shrink-0 transition-transform duration-700 px-[10px]"
:style="{ transform }"
>
<SchemaInput
:tabindex="step !== 1 ? -1 : 0"
name="expiryDate"
type="date"
label="Expiry date"
></SchemaInput>
<form @submit="onSubmit" class="flex flex-col justify-between gap-4">
<FormStepper class="px-[10px]" :step="step"></FormStepper>
<div class="flex overflow-hidden items-center h-auto">
<div
class="w-full shrink-0 transition-transform duration-700 px-[10px]"
:style="{ transform }"
>
<SchemaInput
name="password"
type="password"
label="Encryption password"
:disabled="!values.isPasswordRequired"
></SchemaInput>
<CheckboxSchemaInput
name="isPasswordRequired"
:checked-value="true"
label="Password required"
></CheckboxSchemaInput>
</div>
<div
class="w-full shrink-0 transition-transform duration-700 px-[10px]"
:style="{ transform }"
>
<SchemaInput
:tabindex="step !== 1 ? -1 : 0"
name="expiryDate"
type="date"
label="Optional expiry date"
></SchemaInput>
</div>
<div
class="w-full shrink-0 transition-transform duration-700 px-[10px]"
:style="{ transform }"
>
<FileInput
v-show="step === 2"
:files="files"
:is-upload-setup="isUploadSetup"
@on-fiels-change="(value) => onFilesChange(value)"
@on-cancel="(value) => onCancel(value)"
@on-pause="(value) => onPause(value)"
@on-resume="(value) => onResume(value)"
@on-file-remove="
(value) => {
files.delete(value);
fileKeys.delete(value.name);
}
"
></FileInput>
</div>
</div>
<div
class="w-full shrink-0 transition-transform duration-700 px-[10px]"
:style="{ transform }"
class="flex gap-3 md:gap-0 flex-col-reverse md:flex-row justify-between items-center px-[10px]"
>
<FileInput
:files="files"
:is-upload-setup="isUploadSetup"
@on-fiels-change="(value) => onFilesChange(value)"
@on-cancel="(value) => onCancel(value)"
@on-pause="(value) => onPause(value)"
@on-resume="(value) => onResume(value)"
@on-file-remove="
(value) => {
files.delete(value);
fileKeys.delete(value.name);
}
"
></FileInput>
</div>
</div>
<div
class="flex gap-3 md:gap-0 flex-col-reverse md:flex-row justify-between items-center px-[10px]"
>
<div class="flex gap-3 flex-col md:flex-row w-full md:w-auto md:gap-2">
<div class="flex gap-3 flex-col md:flex-row w-full md:w-auto md:gap-2">
<StyledButton
type="button"
class="w-full md:w-auto"
:category="ButtonType.primary"
:disabled="step === 0 || isLoading || isUploadSetup"
@click="step -= 1"
>Back</StyledButton
>
<StyledButton
type="button"
:disabled="(step === 0 && !meta.dirty) || isLoading"
:category="ButtonType.cancel"
class="w-full md:w-auto"
@click="formReset()"
>Reset</StyledButton
>
</div>
<StyledButton
type="button"
class="w-full md:w-auto"
:category="ButtonType.primary"
:disabled="step === 0 || isLoading || isUploadSetup"
@click="step -= 1"
>Back</StyledButton
>
<StyledButton
type="button"
:disabled="(step === 0 && !meta.dirty) || isLoading"
:category="ButtonType.cancel"
class="w-full md:w-auto"
@click="formReset()"
>Reset</StyledButton
:disabled="!meta.valid || isLoading"
type="submit"
>
<span class="flex items-center justify-center">
{{ step < 2 ? "Next" : "Upload" }}
<LoadingIndicator
v-if="isLoading"
class="w-5 h-5 ml-2"
></LoadingIndicator>
</span>
</StyledButton>
</div>
<StyledButton
class="w-full md:w-auto"
:category="ButtonType.primary"
:disabled="!meta.valid || isLoading"
type="submit"
>
<span class="flex items-center justify-center">
{{ step < 2 ? "Next" : "Upload" }}
<LoadingIndicator
v-if="isLoading"
class="w-5 h-5 ml-2"
></LoadingIndicator>
</span>
</StyledButton>
</div>
</form>
<ConfirmModalVue v-if="isRevealed" @close-click="confirm(true)">
<template #header>Share your files</template>
<template #body>
<SimpleInput
:value="createDownloadUrl()"
label="Share your files"
name="downloadUrl"
></SimpleInput>
</template>
<template #footer>
<StyledButton @click="copyToClipboard()" :category="ButtonType.primary"
>Copy to clipboard</StyledButton
>
</template>
</ConfirmModalVue>
</form>
<ConfirmModalVue v-if="isRevealed" @close-click="confirm(true)">
<template #header>Share your files</template>
<template #body>
<SimpleInput
:value="createDownloadUrl()"
label="Share your files"
name="downloadUrl"
></SimpleInput>
</template>
<template #footer>
<StyledButton @click="copyToClipboard()" :category="ButtonType.primary"
>Copy to clipboard</StyledButton
>
</template>
</ConfirmModalVue>
</div>
</template>

<script setup lang="ts">
Expand Down Expand Up @@ -279,8 +278,9 @@ const onSubmit = handleSubmit(async () => {
openDanger("Upload failed, try again.");
formReset();
}
} else {
step.value++;
}
if (step.value < 2) step.value++;
});
const onCancel = async (fileObj: File) => {
const controller = controllers.get(fileObj.name);
Expand Down Expand Up @@ -350,10 +350,10 @@ const createDownloadUrl = () => {
const key = values.isPasswordRequired
? keychain.getHash()
: btoa(String.fromCharCode(...keychain.getMasterKey()));
downloadUrl = window.location
downloadUrl = window.location.origin
.toString()
.concat(
`download/${uuid}?pass=${values.isPasswordRequired}#${base64Salt}_${key}`
`/download/${uuid}?pass=${values.isPasswordRequired}#${base64Salt}_${key}`
);
return downloadUrl;
};
Expand Down
22 changes: 22 additions & 0 deletions SecureSend/ClientApp/src/views/LandingView.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<template>
<div
class="max-w-5xl mx-auto pt-20 sm:pt-24 lg:pt-32 flex flex-col gap-4 items-center"
>
<h1
class="font-extrabold text-4xl sm:text-5xl lg:text-6xl tracking-tight text-center"
>
Share your files securely.
</h1>
<p class="text-lg text-center max-w-3xl mx-auto text-slate-400">
Secure Send lets you share files with end-to-end encryption. Set your
upload to expire whenever you want and generate a link to access the
upload.
</p>
<router-link
to="/upload"
class="text-white focus:ring-4 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-blue-800"
>
Get started
</router-link>
</div>
</template>

0 comments on commit 48dc822

Please sign in to comment.