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

Merge Usability Changes to Main #52

Merged
merged 26 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c3af97a
Got graph to appear behind contact us model
schromya Nov 25, 2023
a0f09f0
Fixed bug where new users could not log in
schromya Nov 25, 2023
0928db6
some spacing changes in Graph.js
eleonora-sc Nov 25, 2023
9d98e6c
Added dropdown movemnt
schromya Nov 26, 2023
7eaf042
Commented out some non-functional components for demo
schromya Nov 26, 2023
2a03ee9
Adjusted images in navbar
schromya Nov 26, 2023
4d88c84
Created website title and link in navbar
schromya Nov 26, 2023
eae923d
added context menu
AKashton Nov 26, 2023
91fb406
Added to home page
schromya Nov 26, 2023
ffd90be
Fixed formatting for the evil linter
schromya Nov 26, 2023
4a2d99c
added graph context menu functionality
AKashton Nov 26, 2023
df2f66b
adjusted context menu display
AKashton Nov 26, 2023
f1e7969
Merge pull request #51 from quayside-app/usability
schromya Nov 26, 2023
69a7369
clicking on a node pulls up a prompt to update its text, routing work…
eleonora-sc Nov 26, 2023
ab6b753
fixed merge conflicts
eleonora-sc Nov 26, 2023
7dd2530
changed editing a task now works when you go to edit in cxtmenu inste…
eleonora-sc Nov 26, 2023
5c0cb37
small change
eleonora-sc Nov 26, 2023
1a51d9e
changed how the graph looks a little
eleonora-sc Nov 26, 2023
b45833a
dagre layout style
eleonora-sc Nov 26, 2023
07a3c02
sideways graph
eleonora-sc Nov 26, 2023
95fb216
added modal to edit task instead of a prommpt, the modal needs refini…
eleonora-sc Nov 26, 2023
d70806d
ran npx standard fix
eleonora-sc Nov 26, 2023
4dc604d
modal for ediitng a task
eleonora-sc Nov 26, 2023
0f6eb80
Merge branch 'dev' of https://github.com/quayside-app/quayside_mvp in…
eleonora-sc Nov 26, 2023
4f91817
Merge pull request #53 from quayside-app/graph_improv
schromya Nov 26, 2023
6375432
fixed too zoomed in
eleonora-sc Nov 27, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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