Skip to content

Commit

Permalink
Merge pull request #33 from HF6-PROJECT/kbi-28
Browse files Browse the repository at this point in the history
feat: Websockets on FileView
  • Loading branch information
frederikpyt authored Oct 16, 2023
2 parents c9e561f + 9c8f7df commit 3e83d37
Show file tree
Hide file tree
Showing 16 changed files with 102 additions and 81 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA/nqSs2DZmox+sRNR9d9XdaO3C2yJABIO5gdJlBcswNI=
-----END PUBLIC KEY-----"

PUBLIC_PUSHER_APP_KEY="3a4575271634ad5a09ef"
PUBLIC_PUSHER_APP_CLUSTER="eu"

PUBLIC_LIVEBLOCKS_API_KEY="pk_dev_Nwp6X3J4wQWoOKenVZfTTo20uVznlY5ir2_W95bx0RjleqvW7LKKMlPbCZISFsYI"
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"flowbite-typography": "^1.0.3",
"jose": "^4.15.1",
"nanostores": "^0.9.3",
"pusher-js": "^8.3.0",
"tailwind-scrollbar": "^3.0.5",
"tailwindcss": "^3.3.3",
"typescript": "^5.2.2",
Expand Down
60 changes: 0 additions & 60 deletions src/components/TestForm.vue

This file was deleted.

55 changes: 43 additions & 12 deletions src/components/item/Browser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ import { fetchFromApi } from '@lib/helpers';
// Stores
import { useStore } from '@nanostores/vue';
import { addItem, itemsStore } from '@stores/items';
import { addItem, removeItem, itemsStore } from '@stores/items';
import { isModalOpen } from '@stores/modal';
// Components
Expand All @@ -90,6 +90,10 @@ const props = defineProps({
type: Object as PropType<FolderType>,
required: false,
},
user: {
type: Object as PropType<User>,
required: true,
},
});
const fileBrowserContextMenu = ref<InstanceType<typeof ContextMenu>>();
Expand All @@ -109,7 +113,7 @@ const toasts = ref<{ message: string; type: ToastType }[]>([]);
/**
* Items
*/
import { ItemClass } from '@lib/items/items';
import { ItemClass, type ItemType } from '@lib/items/items';
import { ItemFactory } from '@lib/items/factory';
import NoFiles from './file/NoFiles.vue';
Expand Down Expand Up @@ -192,16 +196,6 @@ async function uploadFiles(e: Event) {
Array.from(fileInput.files).forEach(async (file) => {
try {
await FileClass.create(file, props.modelValue ?? null);
// TODO: replace waiting 1 second with websocket
setTimeout(async () => {
await getItems();
toasts.value.push({
message: `File ${file.name} uploaded`,
type: ToastType.Success,
});
}, 1000);
} catch (error) {
toasts.value.push({
message: `Failed to upload file ${file.name}`,
Expand All @@ -223,4 +217,41 @@ const createDocsModal = ref<InstanceType<typeof CreateDocsModal>>();
const docs = computed(() => {
return Object.values(items.value).filter((item) => item instanceof DocsClass) as DocsClass[];
});
/**
* Live Updates
*/
import { getFolderChannel } from '@lib/pusher';
const channel = getFolderChannel(props.user.id, props.modelValue?.id);
channel.bind('update', (data: ItemType) => {
if (!ItemClass.isItem(data)) return;
const item = ItemFactory.getItemFromObject(data);
if (item === null) return;
const isNew = items.value[item.id] === undefined;
const isOwner = item.ownerId === props.user.id;
if (isNew && isOwner) {
// TODO: Fix toasts
toasts.value.push({
message: `${item.name} has been created`,
type: ToastType.Success,
});
}
addItem(item);
});
channel.bind('delete', (data: ItemType) => {
if (!ItemClass.isItem(data)) return;
const item = ItemFactory.getItemFromObject(data);
if (item === null) return;
removeItem(item);
});
</script>
4 changes: 4 additions & 0 deletions src/components/item/ShareItemModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ async function getItem() {
rawItem.ItemSharing.forEach(
(sharing: { id: number; user: { id: number; name: string; email: string } }) => {
if (sharing.user.id === rawItem.owner.id) {
return;
}
usersWithAccess.value.push({
id: sharing.user.id,
sharingId: sharing.id,
Expand Down
7 changes: 6 additions & 1 deletion src/components/item/docs/EditModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,15 @@ async function updateFile() {
// TODO: Show success toast
close(false);
} catch (e) {}
} catch (e) {
console.error('Error: ' + e);
}
}
function open() {
docs.value = {
name: props.docs.name,
};
modal.value?.open();
}
Expand Down
3 changes: 3 additions & 0 deletions src/components/item/file/EditModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ async function updateFile() {
}
function open() {
file.value = {
name: props.file.name,
};
modal.value?.open();
}
Expand Down
4 changes: 4 additions & 0 deletions src/components/item/folder/EditModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ async function updateFolder() {
}
function open() {
folder.value = {
name: props.folder.name,
color: props.folder.color,
};
modal.value?.open();
}
Expand Down
3 changes: 3 additions & 0 deletions src/env.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/// <reference types="astro/client" />

interface User {
id: number;
name: string;
email: string;
}
Expand All @@ -13,6 +14,8 @@ interface ImportMetaEnv {
readonly PUBLIC_LOCAL_DEVELOPMENT_API_URL: string | undefined;
readonly JWT_PUBLIC_KEY: string;
readonly NODE_BUILD: boolean | undefined;
readonly PUBLIC_PUSHER_APP_KEY: string;
readonly PUBLIC_PUSHER_APP_CLUSTER: string;
}

interface ImportMeta {
Expand Down
8 changes: 4 additions & 4 deletions src/lang/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default {
submit: 'Edit',
},
action: {
create: 'Upload fil',
create: 'Upload file',
edit: 'Rename file',
share: 'Share',
delete: 'Delete',
Expand Down Expand Up @@ -112,12 +112,12 @@ export default {
submit: 'Edit',
},
action: {
create: 'Create Docs',
edit: 'Rename Docs',
create: 'Create docs',
edit: 'Rename docs',
share: 'Share',
delete: 'Delete',
openInNewTab: 'Open in new tab',
confirmDelete: 'Are you sure you want to delete this Docs?',
confirmDelete: 'Are you sure you want to delete this docs?',
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion src/lib/items/docs.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ItemClass, type ItemType } from './items';
import { type FolderType } from './folders';
import { api } from '@lib/helpers';
import { api, fetchFromApi } from '@lib/helpers';

export class DocsClass extends ItemClass {
private _text: string;
Expand Down
13 changes: 13 additions & 0 deletions src/lib/pusher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Pusher from 'pusher-js';

const pusher = new Pusher(import.meta.env.PUBLIC_PUSHER_APP_KEY, {
cluster: import.meta.env.PUBLIC_PUSHER_APP_CLUSTER,
});

const getFolderChannel = (userId: number, itemId: number | null | undefined) => {
const channelName = itemId ? `browser-folder-${itemId}` : `browser-root-${userId}`;

return pusher.subscribe(channelName);
};

export { pusher, getFolderChannel };
2 changes: 1 addition & 1 deletion src/middleware/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const user = defineMiddleware(async ({ locals, request, redirect }, next)
}

// Otherwise, set the user data in the locals.
locals.user = userResponse as User;
locals.user = { id: locals.userId, ...userResponse } as User;

return next();
});
Expand Down
2 changes: 1 addition & 1 deletion src/pages/u/folder/[id].astro
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ const user = Astro.locals.user as User;

<LayoutSidebar user={user}>
<div class="h-screen">
<Browser modelValue={folder} client:only />
<Browser modelValue={folder} user={user} client:only />
</div>
</LayoutSidebar>
2 changes: 1 addition & 1 deletion src/pages/u/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ const user = Astro.locals.user as User;

<LayoutSidebar user={user}>
<div class="h-screen">
<Browser modelValue={{}} client:only />
<Browser modelValue={{}} user={user} client:only />
</div>
</LayoutSidebar>

0 comments on commit 3e83d37

Please sign in to comment.