mirror of
https://gitea.smigz.com/smiggiddy/odin-codeprojects.git
synced 2025-06-27 11:20:40 -04:00
Compare commits
2 commits
269d7784ab
...
5ab9f0b2c2
Author | SHA1 | Date | |
---|---|---|---|
5ab9f0b2c2 | |||
8be819bf91 |
16 changed files with 443 additions and 103 deletions
133
.dockerignore
Normal file
133
.dockerignore
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
*.db
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# vuepress v2.x temp and cache directory
|
||||||
|
.temp
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Docusaurus cache and generated files
|
||||||
|
.docusaurus
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.*
|
||||||
|
|
||||||
|
.DS_STORE
|
|
@ -25,22 +25,23 @@ model User {
|
||||||
}
|
}
|
||||||
|
|
||||||
model File {
|
model File {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
name String @db.VarChar(255)
|
name String @db.VarChar(255)
|
||||||
url String
|
url String
|
||||||
size Int
|
size Int
|
||||||
mimetype String
|
mimetype String
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
owner User? @relation(fields: [ownerId], references: [id])
|
modifiedAt DateTime @default("2020-03-19T14:21:00+02:00")
|
||||||
ownerId String?
|
owner User? @relation(fields: [ownerId], references: [id])
|
||||||
folder Folder? @relation(fields: [folderId], references: [id])
|
ownerId String?
|
||||||
folderId String?
|
folder Folder? @relation(fields: [folderId], references: [id])
|
||||||
|
folderId String?
|
||||||
}
|
}
|
||||||
|
|
||||||
model Folder {
|
model Folder {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
name String @db.VarChar(255)
|
name String @db.VarChar(255)
|
||||||
creation_date DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
modification_date DateTime @default(now())
|
modification_date DateTime @default(now())
|
||||||
File File[]
|
File File[]
|
||||||
owner User? @relation(fields: [owner_user_id], references: [id])
|
owner User? @relation(fields: [owner_user_id], references: [id])
|
||||||
|
|
|
@ -24,6 +24,11 @@ body {
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
/* 6. Improve media defaults */
|
/* 6. Improve media defaults */
|
||||||
img,
|
img,
|
||||||
picture,
|
picture,
|
||||||
|
@ -134,9 +139,32 @@ input[type='file']:focus::file-selector-button {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .file { */
|
main {
|
||||||
/* opacity: 0; */
|
display: flex;
|
||||||
/* width: 0.1px; */
|
justify-content: center;
|
||||||
/* height: 0.1px; */
|
width: 100%;
|
||||||
/* position: absolute; */
|
}
|
||||||
/* } */
|
|
||||||
|
main > div {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
aside {
|
||||||
|
min-width: 250px;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.directory-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
const multer = require('multer');
|
const multer = require('multer');
|
||||||
const Db = require('../models/db');
|
|
||||||
const {
|
const {
|
||||||
uploadFile,
|
uploadToStorage,
|
||||||
mkDirectory,
|
mkDirectory,
|
||||||
getDirectoryContents,
|
getDirectoryContents,
|
||||||
getProperPath,
|
createFileRecord,
|
||||||
|
getFileMetaData,
|
||||||
|
editFile,
|
||||||
} = require('../services/fileService');
|
} = require('../services/fileService');
|
||||||
// const storage = multer.memoryStorage();
|
const { getFullUploadPath, formatBytes } = require('../utils/formatHelpers');
|
||||||
// const upload = multer({ storage: storage });
|
const { Prisma } = require('@prisma/client');
|
||||||
const upload = multer({ dest: '/tmp/odin/' });
|
const upload = multer({ dest: '/tmp/odin/' });
|
||||||
|
|
||||||
const db = new Db();
|
|
||||||
|
|
||||||
const createDirectory = async (req, res) => {
|
const createDirectory = async (req, res) => {
|
||||||
const { parentId, 'directory-name': directoryName } = req.body;
|
const { parentId, 'directory-name': directoryName } = req.body;
|
||||||
const referer = req.get('referer');
|
const referer = req.get('referer');
|
||||||
|
@ -28,35 +27,45 @@ const fileUpload = async (req, res) => {
|
||||||
const { folderId, folderName } = req.body;
|
const { folderId, folderName } = req.body;
|
||||||
const referer = req.get('referer');
|
const referer = req.get('referer');
|
||||||
|
|
||||||
let fullPath = await getProperPath(folderId);
|
|
||||||
fullPath =
|
|
||||||
fullPath === '/' ? `/${folderName}` : fullPath + `/${folderName}`;
|
|
||||||
|
|
||||||
const path = `${req.user.username}/${fullPath}/${req.file.originalname}`;
|
|
||||||
const file = {
|
|
||||||
name: req.file.originalname,
|
|
||||||
path: path,
|
|
||||||
folderId: folderId,
|
|
||||||
mimetype: req.file.mimetype,
|
|
||||||
size: req.file.size,
|
|
||||||
};
|
|
||||||
const data = {
|
|
||||||
name: req.file.originalname,
|
|
||||||
path: path,
|
|
||||||
data: req.file.filename,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const supabaseResult = await uploadFile(data);
|
const path = await getFullUploadPath(
|
||||||
if (supabaseResult.error === null) {
|
folderId,
|
||||||
const result = await db.file.createFile(req.user.id, file);
|
folderName,
|
||||||
console.log(result);
|
req.user.username,
|
||||||
|
req.file.originalname,
|
||||||
|
);
|
||||||
|
|
||||||
|
const fileMetaData = {
|
||||||
|
name: req.file.originalname,
|
||||||
|
path: path,
|
||||||
|
folderId: folderId,
|
||||||
|
mimetype: req.file.mimetype,
|
||||||
|
size: req.file.size,
|
||||||
|
};
|
||||||
|
const data = {
|
||||||
|
name: req.file.originalname,
|
||||||
|
path: path,
|
||||||
|
data: req.file.filename,
|
||||||
|
};
|
||||||
|
|
||||||
|
const supabaseResult = await uploadToStorage(data);
|
||||||
|
if (!supabaseResult.error) {
|
||||||
|
// make sure the uploaded file and the db have the same ID
|
||||||
|
fileMetaData.id = supabaseResult.data.id;
|
||||||
|
const result = await createFileRecord(req.user.id, fileMetaData);
|
||||||
|
if (result instanceof Prisma.PrismaClientKnownRequestError) {
|
||||||
|
// if user uploads the samefile name, just overwrite it
|
||||||
|
await editFile(fileMetaData);
|
||||||
|
}
|
||||||
|
res.redirect(referer);
|
||||||
|
} else {
|
||||||
|
console.error(supabaseResult.error);
|
||||||
|
res.status(500).redirect(referer);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
res.status(500).redirect(referer);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.redirect(referer);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const directoryContents = async (req, res) => {
|
const directoryContents = async (req, res) => {
|
||||||
|
@ -74,6 +83,31 @@ const directoryContents = async (req, res) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFiles = (req, res) => {};
|
const getFileData = async (req, res) => {
|
||||||
|
const { fileId } = req.query;
|
||||||
|
|
||||||
module.exports = { createDirectory, upload, fileUpload, directoryContents };
|
try {
|
||||||
|
const file = await getFileMetaData(fileId);
|
||||||
|
file.size = formatBytes(file.size);
|
||||||
|
|
||||||
|
res.render('partials/fileInfo', {
|
||||||
|
file: file,
|
||||||
|
pageTitle: 'FileUpload - File Details',
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
res.redirect('/');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const editFilePost = async (req, res) => {
|
||||||
|
const { id, name, url, modifiedAt, mimetype } = req.body;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createDirectory,
|
||||||
|
upload,
|
||||||
|
fileUpload,
|
||||||
|
directoryContents,
|
||||||
|
getFileData,
|
||||||
|
};
|
||||||
|
|
|
@ -2,9 +2,10 @@ const {
|
||||||
getDirectoryContents,
|
getDirectoryContents,
|
||||||
getParentDirectories,
|
getParentDirectories,
|
||||||
} = require('../services/fileService');
|
} = require('../services/fileService');
|
||||||
|
const { formatBytes } = require('../utils/formatHelpers');
|
||||||
|
|
||||||
const indexGet = async (req, res) => {
|
const indexGet = async (req, res) => {
|
||||||
if (req.user) {
|
if (req.isAuthenticated()) {
|
||||||
res.redirect(`/fs/${req.user.username}/${req.user.rootDirectoryId}`);
|
res.redirect(`/fs/${req.user.username}/${req.user.rootDirectoryId}`);
|
||||||
// if unauthenticated redirect
|
// if unauthenticated redirect
|
||||||
} else {
|
} else {
|
||||||
|
@ -27,6 +28,7 @@ const userDirectoryNavigation = async (req, res) => {
|
||||||
folder: { id: directoryId, name: dirContents.name },
|
folder: { id: directoryId, name: dirContents.name },
|
||||||
directoryListing: dirContents,
|
directoryListing: dirContents,
|
||||||
parentDirectories: parentDirectories,
|
parentDirectories: parentDirectories,
|
||||||
|
formatBytes: formatBytes,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ passport.deserializeUser(async (id, done) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const loggedIn = function (req, res, next) {
|
const loggedIn = function (req, res, next) {
|
||||||
if (!req.user) res.redirect('/');
|
if (!req.isAuthenticated()) res.redirect('/');
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const { PrismaClient } = require('@prisma/client');
|
const { Prisma, PrismaClient } = require('@prisma/client');
|
||||||
|
|
||||||
class File {
|
class File {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -87,8 +87,6 @@ class File {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDirectoriesByUser() {}
|
|
||||||
|
|
||||||
async createFile(userId, file) {
|
async createFile(userId, file) {
|
||||||
try {
|
try {
|
||||||
const result = await this.prisma.file.create({
|
const result = await this.prisma.file.create({
|
||||||
|
@ -99,6 +97,48 @@ class File {
|
||||||
url: file.path,
|
url: file.path,
|
||||||
folderId: file.folderId,
|
folderId: file.folderId,
|
||||||
ownerId: userId,
|
ownerId: userId,
|
||||||
|
id: file.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
} catch (e) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async editFile(file) {
|
||||||
|
const data = await this.prisma.file.update({
|
||||||
|
where: { id: file.id },
|
||||||
|
data: {
|
||||||
|
name: file.name,
|
||||||
|
size: file.size,
|
||||||
|
mimetype: file.mimetype,
|
||||||
|
url: file.path,
|
||||||
|
modifiedAt: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteFile(userId, fileId) {
|
||||||
|
try {
|
||||||
|
const result = await this.prisma.file.delete({
|
||||||
|
data: {
|
||||||
|
id: fileId,
|
||||||
|
ownerId: userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async getFileMetaData(fileId) {
|
||||||
|
try {
|
||||||
|
const result = await this.prisma.file.findUnique({
|
||||||
|
where: {
|
||||||
|
id: fileId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -11,5 +11,6 @@ fileRouter.post(
|
||||||
);
|
);
|
||||||
fileRouter.post('/directory', loggedIn, fileController.createDirectory);
|
fileRouter.post('/directory', loggedIn, fileController.createDirectory);
|
||||||
fileRouter.get('/directory', loggedIn, fileController.directoryContents);
|
fileRouter.get('/directory', loggedIn, fileController.directoryContents);
|
||||||
|
fileRouter.get('/file', loggedIn, fileController.getFileData);
|
||||||
|
|
||||||
module.exports = fileRouter;
|
module.exports = fileRouter;
|
||||||
|
|
|
@ -8,6 +8,14 @@ const supabase = createClient(supabaseUrl, supabaseKey);
|
||||||
|
|
||||||
const db = new Db();
|
const db = new Db();
|
||||||
|
|
||||||
|
async function createFileRecord(userId, fileData) {
|
||||||
|
return await db.file.createFile(userId, fileData);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function editFile(file) {
|
||||||
|
return await db.file.editFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
async function getDirectoryContents(directoryId, userId) {
|
async function getDirectoryContents(directoryId, userId) {
|
||||||
return await db.file.getDirectoryContents(directoryId, userId);
|
return await db.file.getDirectoryContents(directoryId, userId);
|
||||||
}
|
}
|
||||||
|
@ -16,10 +24,10 @@ async function getParentDirectories(directoryId) {
|
||||||
return await db.file.getParentFolders(directoryId);
|
return await db.file.getParentFolders(directoryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadFile(file) {
|
async function uploadToStorage(file) {
|
||||||
const { data, error } = await supabase.storage
|
const { data, error } = await supabase.storage
|
||||||
.from('odin')
|
.from('odin')
|
||||||
.upload(file.path, file.data);
|
.upload(file.path, file.data, { upsert: true });
|
||||||
|
|
||||||
return { data: data, error: error };
|
return { data: data, error: error };
|
||||||
}
|
}
|
||||||
|
@ -52,11 +60,18 @@ async function getProperPath(directoryId) {
|
||||||
return directories.join('/');
|
return directories.join('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getFileMetaData(fileId) {
|
||||||
|
return await db.file.getFileMetaData(fileId);
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
uploadFile,
|
createFileRecord,
|
||||||
|
editFile,
|
||||||
|
uploadToStorage,
|
||||||
mkDirectory,
|
mkDirectory,
|
||||||
getParentDirectories,
|
getParentDirectories,
|
||||||
getDirectoryContents,
|
getDirectoryContents,
|
||||||
getProperPath,
|
getProperPath,
|
||||||
rmDirectory,
|
rmDirectory,
|
||||||
|
getFileMetaData,
|
||||||
};
|
};
|
||||||
|
|
32
file-uploader/src/utils/formatHelpers.js
Normal file
32
file-uploader/src/utils/formatHelpers.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
const { getProperPath } = require('../services/fileService');
|
||||||
|
|
||||||
|
const getFullUploadPath = async (folderId, folderName, username, filename) => {
|
||||||
|
let fullPath = await getProperPath(folderId);
|
||||||
|
fullPath = fullPath === '/' ? `${folderName}` : fullPath + `/${folderName}`;
|
||||||
|
|
||||||
|
return `${username}/${fullPath}/${filename}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatBytes = (bytes, decimals = 2) => {
|
||||||
|
if (!+bytes) return '-';
|
||||||
|
|
||||||
|
const k = 1024;
|
||||||
|
const dm = decimals < 0 ? 0 : decimals;
|
||||||
|
const sizes = [
|
||||||
|
'Bytes',
|
||||||
|
'KiB',
|
||||||
|
'MiB',
|
||||||
|
'GiB',
|
||||||
|
'TiB',
|
||||||
|
'PiB',
|
||||||
|
'EiB',
|
||||||
|
'ZiB',
|
||||||
|
'YiB',
|
||||||
|
];
|
||||||
|
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
|
||||||
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { formatBytes, getFullUploadPath };
|
|
@ -1,20 +1,33 @@
|
||||||
<%- include('partials/header') %>
|
<%- include('partials/header') %>
|
||||||
<body>
|
<body>
|
||||||
<% if(currentUser) { %>
|
<% if(currentUser) { %>
|
||||||
<p> Hello <%= currentUser.username %> </p>
|
<div class="container flex app">
|
||||||
<a href="/auth/logout">sign out</a>
|
<aside class="nav">
|
||||||
<%- include('partials/fileUpload') %>
|
<p> Hello <%= currentUser.username %> </p>
|
||||||
<%- include('partials/parentDirectories') %>
|
<a href="/auth/logout">sign out</a>
|
||||||
<%- include('partials/directoryListing') %>
|
<%- include('partials/newDirectory') %>
|
||||||
|
<%- include('partials/fileUpload') %>
|
||||||
|
</aside>
|
||||||
|
<main>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
|
||||||
|
<%- include('partials/parentDirectories') %>
|
||||||
|
<%- include('partials/directoryListing') %>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<form action="/auth/login" method="post">
|
<main>
|
||||||
<label for="username">Username</label>
|
<form action="/auth/login" method="post">
|
||||||
<input type="text" name="username">
|
<label for="username">Username</label>
|
||||||
<label for="password">Password</label>
|
<input type="text" name="username">
|
||||||
<input type="password" name="password" id="password">
|
<label for="password">Password</label>
|
||||||
<button type="submit">Submit</button>
|
<input type="password" name="password" id="password">
|
||||||
<a href="/auth/register">Click here to register</a>
|
<button type="submit">Submit</button>
|
||||||
</form>
|
<a href="/auth/register">Click here to register</a>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
|
@ -1,12 +1,40 @@
|
||||||
<div class="container">
|
<section class="container directory-listing">
|
||||||
<h2> Folders</h2>
|
<div class="directory-grid">
|
||||||
<ul>
|
<div class="col file-name heading directory__grid_heading">
|
||||||
<% directoryListing.Directories.forEach(d => { %>
|
<p class="title__heading">Name</p>
|
||||||
<li><a href="/fs/<%= currentUser.username %>/<%= d.id %>"> <%= d.name %> </a></li>
|
</div>
|
||||||
<% }); %>
|
|
||||||
</ul>
|
<div class="col file-size directory__grid__heading">
|
||||||
<h2> Files: </h2>
|
<p class="title__heading">Size</p>
|
||||||
<% directoryListing.File.forEach(f => { %>
|
</div>
|
||||||
<p> <%= f.name %> <%= f.id %></p>
|
|
||||||
<% }); %>
|
<div class="col file-modified directory__grid__heading">
|
||||||
</div>
|
<p class="title__heading">Created</p>
|
||||||
|
</div>
|
||||||
|
<!-- Combined loop for both directories and files -->
|
||||||
|
<%
|
||||||
|
const renderItem = (item, isDirectory) => {
|
||||||
|
%>
|
||||||
|
<div class="col file-name">
|
||||||
|
<% if (isDirectory) { %>
|
||||||
|
d <a href="/fs/<%= currentUser.username %>/<%= item.id %>"><%= item.name %></a> /
|
||||||
|
<% } else { %>
|
||||||
|
- <%= item.name %> <a href="/file/file?fileId=<%= item.id %>">Details</a>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
<div class="col file-size">
|
||||||
|
<p><%= formatBytes(item?.size) %></p>
|
||||||
|
</div>
|
||||||
|
<div class="col file-modified">
|
||||||
|
<p><%= item?.createdAt %></p>
|
||||||
|
</div>
|
||||||
|
<% }; %>
|
||||||
|
|
||||||
|
<!-- Render directories -->
|
||||||
|
<% directoryListing.Directories.forEach(d => renderItem(d, true)); %>
|
||||||
|
|
||||||
|
<!-- Render files -->
|
||||||
|
<% directoryListing.File.forEach(f => renderItem(f, false)); %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
10
file-uploader/src/views/partials/fileInfo.ejs
Normal file
10
file-uploader/src/views/partials/fileInfo.ejs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="file-metadata">
|
||||||
|
<h2>File: <%= file.name %> </h2>
|
||||||
|
<p>Size: <%= file.size %> </p>
|
||||||
|
<p>Created At: <%= file.createdAt %></p>
|
||||||
|
<p>Modified At: <%= file?.modifiedAt %></p>
|
||||||
|
</div>
|
||||||
|
<a href="/fs/<%= currentUser.username %>/<%= file.folderId %>">Back</a>
|
||||||
|
</div>
|
|
@ -1,18 +1,12 @@
|
||||||
<form action="/file" method="post" enctype="multipart/form-data">
|
<section class="file-upload">
|
||||||
<div class="container file-upload">
|
<h2 class="h2-heading">New upload</h2>
|
||||||
<input type="file" name="fileUpload" id="fileUpload" class="file" required>
|
<form action="/file" method="post" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="folderId" value=<%= folder.id %>>
|
<div class="container file-upload">
|
||||||
<input type="hidden" name="folderName" value=<%= folder.name %>>
|
<input type="file" name="fileUpload" id="fileUpload" class="file" required>
|
||||||
<button type="submit">Upload</button>
|
<input type="hidden" name="folderId" value=<%= folder.id %>>
|
||||||
</div>
|
<input type="hidden" name="folderName" value=<%= folder.name %>>
|
||||||
</form>
|
<button type="submit" class="btn">Upload</button>
|
||||||
|
|
||||||
|
|
||||||
<form action="/file/directory" method="post">
|
|
||||||
<div class="container">
|
|
||||||
<label for="directory-name">Directory Name:</label>
|
|
||||||
<input type="text" name="directory-name" placeholder="" required>
|
|
||||||
<input type="hidden" name="parentId" value=<%= folder.id %>>
|
|
||||||
<button>Create Directory</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
10
file-uploader/src/views/partials/newDirectory.ejs
Normal file
10
file-uploader/src/views/partials/newDirectory.ejs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<form action="/file/directory" method="post">
|
||||||
|
<div class="container">
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="directory-name">Directory Name:</label>
|
||||||
|
<input type="text" name="directory-name" placeholder="" required>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" name="parentId" value=<%= folder.id %>>
|
||||||
|
<button class="btn">Create Directory</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -1,9 +1,8 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<p>
|
<p class="directory-path">
|
||||||
<% parentDirectories.forEach(d => { %>
|
<% parentDirectories.forEach(d => { %>
|
||||||
<a href="/fs/<%= currentUser.username %>/<%= d.id %>"><%= d.name %></a><span> /</span>
|
<a href="/fs/<%= currentUser.username %>/<%= d.id %>"><%= d.name %></a><span> /</span>
|
||||||
|
|
||||||
<% }); %>
|
<% }); %>
|
||||||
<span> <%= directoryListing.name %></span>
|
<span class="current-directory"> <%= directoryListing.name %></span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue