Skip to content

Commit

Permalink
Fix/fix multiple things (#58)
Browse files Browse the repository at this point in the history
* Fix #54

* Fix #56

* Fix #57

* Fix #41

* Fix fragile test
  • Loading branch information
andrewwippler authored Apr 14, 2023
1 parent 6e9a6d5 commit 95527cf
Show file tree
Hide file tree
Showing 13 changed files with 78 additions and 46 deletions.
8 changes: 5 additions & 3 deletions api/app/Controllers/Http/SearchesController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ export default class SearchesController {
}

const illustrations = await Illustration.query()
.where('title', search)
.orWhere('content', 'LIKE', `%${search}%`)
.orWhere('author', 'LIKE', `%${search}%`)
.where((query) => {
query.where('title', search)
.orWhere('content', 'LIKE', `%${search}%`)
.orWhere('author', 'LIKE', `%${search}%`)
})
.andWhere('user_id', `${auth.user?.id}`)
const tagSanitizedSearch = _.startCase(search).replace(/ /g, '-')
const tags = await Tag.query().where('name',tagSanitizedSearch).andWhere('user_id', `${auth.user?.id}`)
Expand Down
6 changes: 3 additions & 3 deletions api/tests/functional/user.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ test.group('Users', (group) => {
const user = await UserFactory.make()
let fixedUser = {
email: user.email,
password: user.password,
password_confirmation: user.password
password: user.password+"1A!a",
password_confirmation: user.password+"1A!a"
}

const response = await client.post('/register').json(fixedUser)
Expand All @@ -24,7 +24,7 @@ test.group('Users', (group) => {
response.assertBodyContains({uid: response.body().uid})
response.assertStatus(200)

const loggedInUser = await client.post('/login').json({email: user.email, password: user.password})
const loggedInUser = await client.post('/login').json({email: user.email, password: user.password+"1A!a"})

const verify = await client.get(`/users/${response.body().uid}`).bearerToken(loggedInUser.body().token)
verify.assertStatus(200)
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/TagSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default function TagSelect({ defaultValue, token }:{ defaultValue: string
const handleKeyPress = (event: KeyboardEvent<HTMLInputElement>) => {
if (event.key === ",") {
event.preventDefault()
if (inputRef.current) {
if (inputRef.current && (inputRef.current.value != "")) {
handleTagAdd(inputRef.current.value)
}
}
Expand Down
10 changes: 8 additions & 2 deletions frontend/src/features/ui/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import type { AppState, AppThunk } from '@/store'
export interface UIState {
illustrationEdit: boolean
updateUI: boolean
redirect: string
}

const initialState: UIState = {
illustrationEdit: false,
updateUI: false
updateUI: false,
redirect: "/",
}

export const uiReducer = createSlice({
Expand All @@ -23,13 +25,17 @@ export const uiReducer = createSlice({
setUpdateUI: (state, actions) => {
state.updateUI = actions.payload
},
setRedirect: (state, actions) => {
state.redirect = actions.payload
},
},


})
export const selectIllustrationEdit = (state: AppState) => state.ui.illustrationEdit
export const selectUpdateUI = (state: AppState) => state.ui.updateUI
export const getRedirect = (state: AppState) => state.ui.redirect

export const { setIllustrationEdit, setUpdateUI } = uiReducer.actions
export const { setIllustrationEdit, setUpdateUI, setRedirect } = uiReducer.actions

export default uiReducer.reducer
5 changes: 0 additions & 5 deletions frontend/src/library/useUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,12 @@ import { useEffect } from 'react'
import Router from 'next/router'
import useSWR from 'swr'
import { User } from '@/pages/api/user'
import { useAppSelector, useAppDispatch } from '@/hooks'

import { setToken } from '@/features/user/reducer';

export default function useUser({
redirectTo = '',
redirectIfFound = false,
} = {}) {
const { data: user, mutate: mutateUser } = useSWR<User>('/api/user')
const dispatch = useAppDispatch()
// dispatch(setToken(user?.token)) // send token for api calls

useEffect(() => {
// if no redirect needed, just return (example: already on /dashboard)
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/pages/author/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Link from 'next/link'
import useUser from '@/library/useUser';
import Layout from '@/components/Layout';
import Head from 'next/head';

import { setRedirect } from '@/features/ui/reducer';
import { useAppSelector, useAppDispatch } from '@/hooks'


Expand All @@ -24,6 +24,7 @@ export default function Author() {
const [isLoading, setLoading] = useState(false)

useEffect(() => {
if (!user?.token) dispatch(setRedirect(`/author/${name}`))
if (!name) {
setLoading(true)
return
Expand All @@ -38,7 +39,7 @@ export default function Author() {
}, [name]);



if (!user?.token) return
if (isLoading) return (
<Layout>
<div>Loading...</div>
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/pages/authors.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import Author from '@/components/AuthorIndex';
import Layout from '@/components/Layout'
import useUser from '@/library/useUser';
import { setRedirect } from '@/features/ui/reducer';
import { useAppDispatch } from '@/hooks'
import { useEffect } from 'react';

export default function Home() {
export default function Authors() {
const { user } = useUser({
redirectTo: '/login',
})

const dispatch = useAppDispatch()
useEffect(() => {
if (!user?.token) dispatch(setRedirect(`/authors`))
}, [user])
if (!user?.token) return
return (
<Layout>
{ user?.isLoggedIn && (<Author token={user?.token} />) }
Expand Down
21 changes: 11 additions & 10 deletions frontend/src/pages/illustration/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { selectModal, setModal } from '@/features/modal/reducer'
import { setFlashMessage } from '@/features/flash/reducer'
import IllustrationForm from '@/components/IllustrationForm';
import { illustrationType } from '@/library/illustrationType';
import { selectIllustrationEdit, setIllustrationEdit, selectUpdateUI, setUpdateUI } from '@/features/ui/reducer';
import { selectIllustrationEdit, setIllustrationEdit, selectUpdateUI, setUpdateUI, setRedirect } from '@/features/ui/reducer';
import format from 'date-fns/format';
import PlaceConfirmDialog from '@/components/PlaceConfirmDialog';
import { placeType } from '@/library/placeType';
Expand All @@ -37,10 +37,11 @@ export default function IllustrationWrapper() {

useEffect(() => {
setLoading(true)
if (!router.query.id || !user) {
if (!user?.token) dispatch(setRedirect(`/illustration/${router.query.id}`))
if (!router.query.id || !user?.token) {
return
}
dispatch(getThunkSettings(user?.token))
dispatch(getThunkSettings(user.token))

api.get(`/illustration/${router.query.id}`, '', user.token)
.then(data => {
Expand Down Expand Up @@ -116,8 +117,8 @@ export default function IllustrationWrapper() {
used: form.Used.value.trim(),
}
}

if (!user?.token || !illustration || !userSettings) return <Layout>Loading...</Layout>
if (!user?.token) return
if (!illustration || !userSettings) return <Layout>Loading...</Layout>
return (
<Layout>
<Head>
Expand All @@ -127,19 +128,19 @@ export default function IllustrationWrapper() {
<IllustrationForm illustration={illustration} />
:
<>
<div className="p-4 bg-gray-50 grid grid-cols-1 md:grid-cols-2">
<div>
<div className="p-4 bg-gray-50 grid grid-cols-1 md:grid-cols-2 ">
<div className='truncate'>
<span className="font-bold pr-2">Title:</span>
{/* Title is required */}
{illustration?.title}
</div>
{illustration?.author &&
<div>
<div className='truncate'>
<span className="font-bold pr-2">Author:</span>
{illustration.author}
</div>}
{illustration?.source && <div>
<span className="font-bold pr-2">Source:</span>
{illustration?.source && <div className='truncate'>
<span className="font-bold pr-2 ">Source:</span>
{isValidHttpUrl(illustration.source) ? <Link href={illustration.source}>{illustration.source}</Link> : illustration.source}
</div>}
{illustration?.tags && <div>
Expand Down
12 changes: 8 additions & 4 deletions frontend/src/pages/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ import useUser from '@/library/useUser'
import Layout from '@/components/Layout'
import Form from '@/components/Form'
import fetchJson, { FetchError } from '@/library/fetchJson'

import { useAppDispatch, useAppSelector } from '@/hooks'
import { getRedirect, setRedirect } from '@/features/ui/reducer';
export default function Login() {
// here we just check if user is already logged in and redirect to profile
// should be last page

const dispatch = useAppDispatch()

// retrieve first accessed path as unauthenticated user
const redirectPath = useAppSelector(getRedirect)
const { mutateUser } = useUser({
redirectTo: '/',
redirectTo: redirectPath,
redirectIfFound: true,
})

Expand Down
14 changes: 10 additions & 4 deletions frontend/src/pages/new-illustration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@ import React, { useState } from 'react'
import useUser from '@/library/useUser'
import Layout from '@/components/Layout'
import IllustrationForm from '@/components/IllustrationForm'
import { setRedirect } from '@/features/ui/reducer';
import { useAppDispatch } from '@/hooks'
import { useEffect } from 'react';

export default function Login() {
// here we just check if user is already logged in and redirect to profile
// should be last page

const { user } = useUser({
redirectTo: '/',
redirectTo: '/login',
})


const dispatch = useAppDispatch()
useEffect(() => {
if (!user?.token) dispatch(setRedirect(`/new-illustration`))
}, [user])
if (!user?.token) return
return (
<Layout>
<IllustrationForm />
Expand Down
12 changes: 8 additions & 4 deletions frontend/src/pages/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { tagType } from '@/library/tagtype'
import { illustrationType } from '@/library/illustrationType'
import { placeType } from '@/library/placeType'
import { MagnifyingGlassCircleIcon } from '@heroicons/react/20/solid'
import { setRedirect } from '@/features/ui/reducer';
import { useEffect } from 'react';

type dataReturn = {
illustrations: any
Expand All @@ -18,16 +20,18 @@ type dataReturn = {
}

export default function Search() {
// here we just check if user is already logged in and redirect to profile
// should be last page
const { user } = useUser({
redirectTo: '/',
redirectTo: '/login',
})

const dispatch = useAppDispatch()
const [data, setData] = useState<dataReturn | null>(null)
const [searched, setSearched] = useState('')

useEffect(() => {
if (!user?.token) dispatch(setRedirect(`/search`))
}, [user])

const onSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
let form = {
Expand All @@ -45,7 +49,7 @@ export default function Search() {
setSearched(form.search)
});
}

if (!user?.token) return
// The UI does not allow the saving of an illustration without tags.
// If it does, then we need to have a listing of those illustrations here.
return (
Expand Down
12 changes: 8 additions & 4 deletions frontend/src/pages/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@ import api from '@/library/api'
import { getSettings, getThunkSettings, setSettings } from '@/features/user/reducer'
import router from 'next/router'
import { ArrowLeftIcon, ClipboardDocumentListIcon } from '@heroicons/react/24/solid'
import { setRedirect } from '@/features/ui/reducer';

export default function Settings() {
// here we just check if user is already logged in and redirect to profile
// should be last page

const { user } = useUser({
redirectTo: '/',
redirectTo: '/login',
})

const dispatch = useAppDispatch()
dispatch(getThunkSettings(user?.token))
const settings = useAppSelector(getSettings)

useEffect(() => {
if (!user?.token) dispatch(setRedirect(`/settings`))
}, [user])

const onSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
let form = grabAndReturnObject(event.currentTarget)
Expand All @@ -41,7 +45,7 @@ export default function Settings() {
location: form.location.value.trim(),
}
}

if (!user?.token) return
return (
<Layout>
{settings && <>
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/pages/tag/[name].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import ConfirmDialog from '@/components/ConfirmDialog';
import { PencilSquareIcon, CheckCircleIcon, TrashIcon } from '@heroicons/react/24/solid'
import { FormEvent } from 'react';
import Head from 'next/head';

import { setRedirect } from '@/features/ui/reducer';
import { useAppSelector, useAppDispatch } from '@/hooks'
import { selectModal, setModal } from '@/features/modal/reducer'
import { setFlashMessage } from '@/features/flash/reducer'
Expand All @@ -29,12 +29,13 @@ export default function Tag() {
const [editTag, setEditTag] = useState(false)

useEffect(() => {
if (!user?.token) dispatch(setRedirect(`/tag/${router.query.name}`))
if (!name) {
setLoading(true)
return
}
// add - for data fetching
api.get(`/tag/${name}`.replace(/ /g, '-'), '', user?.token)
api.get(`/tag/${router.query.name}`, '', user?.token)
.then(data => {
setData(data); // illustrations
setLoading(false)
Expand Down Expand Up @@ -73,7 +74,7 @@ export default function Tag() {
router.replace('/') // go home
});
};

if (!user?.token) return
if (isLoading) return (
<Layout>
<div>Loading...</div>
Expand Down

0 comments on commit 95527cf

Please sign in to comment.