Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
Merge pull request #52 from quayside-app/dev
Browse files Browse the repository at this point in the history
Merge Usability Changes to Main
  • Loading branch information
eleonora-sc authored Nov 27, 2023
2 parents d58f6f3 + 6375432 commit 9a19f36
Show file tree
Hide file tree
Showing 13 changed files with 381 additions and 71 deletions.
46 changes: 42 additions & 4 deletions package-lock.json

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

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
"autoprefixer": "10.4.15",
"cookie-cutter": "^0.2.0",
"cytoscape": "^3.26.0",
"cytoscape-cxtmenu": "^3.5.0",
"cytoscape-dagre": "^2.5.0",
"dotenv": "^16.3.1",
"eslint-config-next": "13.4.19",
"mongodb": "^6.2.0",
Expand Down
18 changes: 9 additions & 9 deletions src/app/api/auth/[...nextauth]/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const options = {
async signIn ({ user, account, profile }) {
const existingUser = await getUsers(null, user.email)

if (existingUser) {
if (existingUser && existingUser.length > 0) {
return true
} else {
// Get first and last name
Expand All @@ -30,24 +30,24 @@ export const options = {
const lastName = nameParts.length > 1 ? nameParts.slice(1).join(' ') : ''

// Create User
const newUser = await createUser(user.email, firstName, lastName)
return !!newUser // Return true if creation is successful
const createdUser = await createUser(user.email, firstName, lastName)
return !!createdUser // Return true if creation is successful
}
},

async session ({ session, user, token }) {
// Assign the user ID to the session to make it available on the client side
session.userId = token.sub // 'sub' is typically the field where the user ID from the provider is stored
return session
},

async jwt ({ token, user, account, profile, isNewUser }) {
// This callback is called whenever a JWT is created. So session.userId is the mongo User _id
if (user) {
const mongoUsers = await getUsers(null, user.email)
token.sub = mongoUsers[0]._id
}
return token
},

async session ({ session, user, token }) {
// Assign the user ID to the session to make it available on the client side
session.userId = token.sub // 'sub' is typically the field where the user ID from the provider is stored
return session
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/app/api/mongoDB/createUser/createUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,12 @@ import { URI } from '../mongoData.js'

export async function createUser (email, firstName = null, lastName = null, username = null, teamIDs = []) {
if (mongoose.connection.readyState !== 1) await mongoose.connect(URI)

const user = await User.create({
email,
firstName,
lastName,
username,
teamIDs
})

return user
}
7 changes: 0 additions & 7 deletions src/app/api/mongoDB/createUser/route.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { options } from '../../auth/[...nextauth]/options'
import { getServerSession } from 'next-auth/next'
import { NextResponse } from 'next/server'
import { createUser } from './createUser'

Expand Down Expand Up @@ -40,11 +38,6 @@ import { createUser } from './createUser'
*/
export async function POST (request) {
try {
const session = await getServerSession(options)
if (!session) {
return NextResponse.json({ success: false, message: 'authentication failed' }, { status: 401 })
}

const params = await request.json()

if (!params.email) {
Expand Down
34 changes: 34 additions & 0 deletions src/app/api/mongoDB/editTask/editTask.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Task } from '../mongoModels'

/**
* Creates and stores a new task in the database. This function can be used server side.
* Alternatively the POST request in the route.js should be used on client side (which uses this logic).
*
* @param {string} taskId - The ObjectID of the task. Required.
* @param {string} name - The name of the task. Required.
* @returns {Promise<Object>} - A promise that resolves to the newly created task object.
*
* @example
* // Example of using editTask function
* const task = await editTask('65627e3f0deac40cffab844c', 'Develop New Feature');
*
*/
export async function editTask (taskId, newName) {
try {
// Find the task by its ObjectId and update its name
const updatedTask = await Task.findByIdAndUpdate(
taskId,
{ name: newName },
{ new: true } // Return the updated document
)

if (!updatedTask) {
throw new Error('Task not found')
}

return updatedTask
} catch (error) {
console.error('Error updating task:', error)
throw error // Re-throw the error for handling at a higher level
}
}
69 changes: 69 additions & 0 deletions src/app/api/mongoDB/editTask/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import mongoose from 'mongoose'
import { options } from '../../auth/[...nextauth]/options'
import { getServerSession } from 'next-auth/next'
import { NextResponse } from 'next/server'
import { URI } from '../mongoData.js'
import { editTask } from './editTask'

/**
* Handles a POST request to create and store a new task in the database. This function
* first authenticates the session, then validates the necessary parameters for task creation,
* such as 'name' and 'projectID'. If the parameters are valid and the associated project exists,
* it proceeds to create a new task with the given details.
*
* @param {Object} request - The request object containing the task details.
* @returns {Object} - A response object with a status code,and the task if completed successfully ({message:<message>, task:{<task>}})
*
* @throws Will throw an error if any of the required fields are missing, if there's an issue connecting
* to the database, or if the session is not authenticated.
*
* @example
* // Example of using this function in a POST request
* fetch(`/api/tasks/createTask`, {
* method: 'POST',
* headers: { 'Content-Type': 'application/json' },
* body: JSON.stringify({
* name: 'New Task',
* projectID: 'proj123',
* // ...other task properties
* }),
* }).then(async (response) => {
* const body = await response.json();
* if (!response.ok) {
* console.error('Task creation failed:', body.message);
* } else {
* console.log('Task created:', body.task);
* }
* }).catch(error => console.error('Error in creating task:', error));
*
* @property {string} request.body.name - The name of the task. (Required)
*/

export async function PUT (request) {
try {
const session = await getServerSession(options)
if (!session) {
return NextResponse.json({ success: false, message: 'Authentication failed' }, { status: 401 })
}

const params = await request.json()

if (!params.taskId || !params.newName) {
return NextResponse.json({ message: 'Task ID and new text are required.' }, { status: 400 })
}

if (mongoose.connection.readyState !== 1) await mongoose.connect(URI)

// const projectExists = await Project.exists({ _id: params.projectID });
// if (!projectExists) {
// return NextResponse.json({ message: `Project ${params.projectID} does not exist.` }, { status: 400 });
// }

const updatedTask = await editTask(params.taskId, params.newName)

return NextResponse.json({ task: updatedTask }, { status: 200 })
} catch (error) {
console.error('Error updating task:', error)
return NextResponse.json({ message: 'Error updating Task: ' + error }, { status: 500 })
}
}
15 changes: 12 additions & 3 deletions src/app/page.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
export default function Home () {
return (
<main className='flex flex-wrap w-full'>
<div className='flex w-full flex-wrap '>
Create or Select a project.
<main className='m-10'>

<div className='flex justify-center w-full text-4xl md:text-7xl font-bold '>
quayside.app
</div>

<div className='flex justify-center w-full md:text-3xl mt-3 '>
Ignite Collaborative Productivity
</div>
<div className='flex justify-center w-full text-sm md:text-xl mt-10 p-1 bg-neutral-700 rounded-lg'>
Create or select a project to get started...
</div>

</main>
)
}
6 changes: 3 additions & 3 deletions src/components/ContactUsModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export default function ContactUsModal ({ isOpen, handleClose }) {
<Input name='email' label='Your Email' placeholder='[email protected]' changeAction={handleInput} value={formData.email} />
<Input name='subject' label='Subject' placeholder='Subject' changeAction={handleInput} value={formData.subject} />
<Input name='message' label='Message' placeholder='Your message here...' changeAction={handleInput} value={formData.message} />
<button type='submit' className='w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 font-medium rounded-lg text-sm px-5 py-2.5 text-center'>
<button type='submit' className='w-full text-white bg-gray-700 hover:bg-blue-800 focus:ring-4 font-medium rounded-lg text-sm px-5 py-2.5 text-center'>
Send
</button>
</form>
Expand All @@ -92,9 +92,9 @@ export default function ContactUsModal ({ isOpen, handleClose }) {
}

return (
<div className='fixed inset-0 bg-gray-500 bg-opacity-75'>
<div className='fixed inset-0 bg-gray-500 bg-opacity-75 z-50'>
<div className='fixed w-full p-4'>
<div className='relative rounded-lg shadow bg-gray-900'>
<div className='relative rounded-lg shadow bg-black'>
<button type='button' onClick={handleClose} className='absolute top-3 right-3 rounded-lg w-8 h-8 inline-flex justify-center items-center hover:bg-gray-600'>
<Image src={xIcon} alt='exit' width='10' height='10' />
</button>
Expand Down
29 changes: 18 additions & 11 deletions src/components/Dropdown.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client'
import React from 'react'
import React, { useState } from 'react'
import Image from 'next/image'

import dropdownIcon from '../../public/svg/dropdown.svg'
Expand All @@ -21,20 +21,27 @@ import dropdownIcon from '../../public/svg/dropdown.svg'
*
* @returns {React.Element} The rendered Dropdown button element.
*/
const Dropdown = ({ label, clickAction, imagePath }) => {
const Dropdown = ({ label, imagePath, dropdownComponents }) => {
const [dropdownHidden, setDropdown] = useState(false)

return (
<div>
<button type='button' onClick={() => setDropdown(!dropdownHidden)} className='flex items-center w-full p-2 text-base text-white transition duration-75 rounded-lg group hover:bg-gray-700' aria-controls='dropdown-example' data-collapse-toggle='dropdown-example'>
<div className='flex w-full'>
<div className='flex w-11/12'>
<Image priority src={imagePath} alt={label} height='20' width='20' />
<span className='flex my-auto ml-3 text-left whitespace-nowrap'>{label}</span>
</div>
<div className={`flex 1-1/12 justify-end my-auto ${dropdownHidden && '-rotate-90'}`}>
<Image priority src={dropdownIcon} alt='Dropdown Icon' height='20' width='20' />
</div>

<button type='button' onClick={clickAction} className='flex items-center w-full p-2 text-base text-white transition duration-75 rounded-lg group hover:bg-gray-700' aria-controls='dropdown-example' data-collapse-toggle='dropdown-example'>
<div className='flex w-full'>
<div className='flex w-11/12'>
<Image priority src={imagePath} alt={label} height='20' width='20' />
<span className='flex my-auto ml-3 text-left whitespace-nowrap'>{label}</span>
</div>
<div className='flex 1-1/12 justify-end '>
<Image priority src={dropdownIcon} alt='Dropdown Icon' height='20' width='20' />
</div>
</button>
<div className={dropdownHidden && 'hidden'}>
{dropdownComponents}
</div>
</button>
</div>

)
}
Expand Down
Loading

0 comments on commit 9a19f36

Please sign in to comment.