diff --git a/waspc/data/Generator/templates/react-app/src/auth/login.js b/waspc/data/Generator/templates/react-app/src/auth/login.js index 402e82ea9..b5b9536bd 100644 --- a/waspc/data/Generator/templates/react-app/src/auth/login.js +++ b/waspc/data/Generator/templates/react-app/src/auth/login.js @@ -1,4 +1,4 @@ -import { removeQueries } from '../operations/resources' +import { invalidateAndRemoveQueries } from '../operations/resources' import api, { setAuthToken, handleApiError } from '../api.js' export default async function login(username, password) { @@ -9,7 +9,7 @@ export default async function login(username, password) { setAuthToken(response.data.token) // This isn't really neccessary because we remove all private queries after // logout, but we do it to be extra safe. - // + // // For example, in future versions, users might be able to get to an SPA // login page while there's an active session. This code will prevent data // leaks in such cases. @@ -17,7 +17,7 @@ export default async function login(username, password) { // TODO(filip): We are currently removing all the queries, but we should // remove only non-public, user-dependent queries - public queries are // expected not to change in respect to the currently logged in user. - await removeQueries() + await invalidateAndRemoveQueries() } catch (error) { handleApiError(error) } diff --git a/waspc/data/Generator/templates/react-app/src/operations/resources.js b/waspc/data/Generator/templates/react-app/src/operations/resources.js index 437668444..70c0458a4 100644 --- a/waspc/data/Generator/templates/react-app/src/operations/resources.js +++ b/waspc/data/Generator/templates/react-app/src/operations/resources.js @@ -40,16 +40,15 @@ export function getActiveOptimisticUpdates(queryKey) { return updateHandlers.getUpdateHandlers(queryKey) } -export async function removeQueries() { - const queryClient = await queryClientInitialized - queryClient.removeQueries() -} - export async function invalidateAndRemoveQueries() { const queryClient = await queryClientInitialized // If we don't reset the queries before removing them, Wasp will stay on // the same page. The user would have to manually refresh the page to "finish" // logging out. + // When a query is removed, the `Observer` is removed as well, and the components + // that are using the query are not re-rendered. This is why we need to reset + // the queries, so that the `Observer` is re-created and the components are re-rendered. + // For more details: https://github.com/wasp-lang/wasp/pull/1014/files#r1111862125 queryClient.resetQueries() // If we don't remove the queries after invalidating them, the old query data // remains in the cache, casuing a potential privacy issue. diff --git a/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/.waspchecksums b/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/.waspchecksums index 421a39f79..e52682c81 100644 --- a/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/.waspchecksums +++ b/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/.waspchecksums @@ -354,7 +354,7 @@ "file", "web-app/src/operations/resources.js" ], - "d815397e45efe773908b48de42f21ee22481396c318b21ea215ad6343d3f4170" + "8bb71b7d7ef3962c28b9db1554500452e7f91b0c9fd898d5cafcdb7229f6db1e" ], [ [ diff --git a/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/web-app/src/operations/resources.js b/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/web-app/src/operations/resources.js index 437668444..70c0458a4 100644 --- a/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/web-app/src/operations/resources.js +++ b/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/web-app/src/operations/resources.js @@ -40,16 +40,15 @@ export function getActiveOptimisticUpdates(queryKey) { return updateHandlers.getUpdateHandlers(queryKey) } -export async function removeQueries() { - const queryClient = await queryClientInitialized - queryClient.removeQueries() -} - export async function invalidateAndRemoveQueries() { const queryClient = await queryClientInitialized // If we don't reset the queries before removing them, Wasp will stay on // the same page. The user would have to manually refresh the page to "finish" // logging out. + // When a query is removed, the `Observer` is removed as well, and the components + // that are using the query are not re-rendered. This is why we need to reset + // the queries, so that the `Observer` is re-created and the components are re-rendered. + // For more details: https://github.com/wasp-lang/wasp/pull/1014/files#r1111862125 queryClient.resetQueries() // If we don't remove the queries after invalidating them, the old query data // remains in the cache, casuing a potential privacy issue. diff --git a/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/.waspchecksums b/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/.waspchecksums index c2feab106..c58f9d854 100644 --- a/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/.waspchecksums +++ b/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/.waspchecksums @@ -354,7 +354,7 @@ "file", "web-app/src/operations/resources.js" ], - "d815397e45efe773908b48de42f21ee22481396c318b21ea215ad6343d3f4170" + "8bb71b7d7ef3962c28b9db1554500452e7f91b0c9fd898d5cafcdb7229f6db1e" ], [ [ diff --git a/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/web-app/src/operations/resources.js b/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/web-app/src/operations/resources.js index 437668444..70c0458a4 100644 --- a/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/web-app/src/operations/resources.js +++ b/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/web-app/src/operations/resources.js @@ -40,16 +40,15 @@ export function getActiveOptimisticUpdates(queryKey) { return updateHandlers.getUpdateHandlers(queryKey) } -export async function removeQueries() { - const queryClient = await queryClientInitialized - queryClient.removeQueries() -} - export async function invalidateAndRemoveQueries() { const queryClient = await queryClientInitialized // If we don't reset the queries before removing them, Wasp will stay on // the same page. The user would have to manually refresh the page to "finish" // logging out. + // When a query is removed, the `Observer` is removed as well, and the components + // that are using the query are not re-rendered. This is why we need to reset + // the queries, so that the `Observer` is re-created and the components are re-rendered. + // For more details: https://github.com/wasp-lang/wasp/pull/1014/files#r1111862125 queryClient.resetQueries() // If we don't remove the queries after invalidating them, the old query data // remains in the cache, casuing a potential privacy issue. diff --git a/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/.waspchecksums b/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/.waspchecksums index a74565c11..4f23fa1f3 100644 --- a/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/.waspchecksums +++ b/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/.waspchecksums @@ -368,7 +368,7 @@ "file", "web-app/src/operations/resources.js" ], - "d815397e45efe773908b48de42f21ee22481396c318b21ea215ad6343d3f4170" + "8bb71b7d7ef3962c28b9db1554500452e7f91b0c9fd898d5cafcdb7229f6db1e" ], [ [ diff --git a/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/web-app/src/operations/resources.js b/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/web-app/src/operations/resources.js index 437668444..70c0458a4 100644 --- a/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/web-app/src/operations/resources.js +++ b/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/web-app/src/operations/resources.js @@ -40,16 +40,15 @@ export function getActiveOptimisticUpdates(queryKey) { return updateHandlers.getUpdateHandlers(queryKey) } -export async function removeQueries() { - const queryClient = await queryClientInitialized - queryClient.removeQueries() -} - export async function invalidateAndRemoveQueries() { const queryClient = await queryClientInitialized // If we don't reset the queries before removing them, Wasp will stay on // the same page. The user would have to manually refresh the page to "finish" // logging out. + // When a query is removed, the `Observer` is removed as well, and the components + // that are using the query are not re-rendered. This is why we need to reset + // the queries, so that the `Observer` is re-created and the components are re-rendered. + // For more details: https://github.com/wasp-lang/wasp/pull/1014/files#r1111862125 queryClient.resetQueries() // If we don't remove the queries after invalidating them, the old query data // remains in the cache, casuing a potential privacy issue. diff --git a/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/.waspchecksums b/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/.waspchecksums index 095a7c658..3719b0fdc 100644 --- a/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/.waspchecksums +++ b/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/.waspchecksums @@ -354,7 +354,7 @@ "file", "web-app/src/operations/resources.js" ], - "d815397e45efe773908b48de42f21ee22481396c318b21ea215ad6343d3f4170" + "8bb71b7d7ef3962c28b9db1554500452e7f91b0c9fd898d5cafcdb7229f6db1e" ], [ [ diff --git a/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/web-app/src/operations/resources.js b/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/web-app/src/operations/resources.js index 437668444..70c0458a4 100644 --- a/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/web-app/src/operations/resources.js +++ b/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/web-app/src/operations/resources.js @@ -40,16 +40,15 @@ export function getActiveOptimisticUpdates(queryKey) { return updateHandlers.getUpdateHandlers(queryKey) } -export async function removeQueries() { - const queryClient = await queryClientInitialized - queryClient.removeQueries() -} - export async function invalidateAndRemoveQueries() { const queryClient = await queryClientInitialized // If we don't reset the queries before removing them, Wasp will stay on // the same page. The user would have to manually refresh the page to "finish" // logging out. + // When a query is removed, the `Observer` is removed as well, and the components + // that are using the query are not re-rendered. This is why we need to reset + // the queries, so that the `Observer` is re-created and the components are re-rendered. + // For more details: https://github.com/wasp-lang/wasp/pull/1014/files#r1111862125 queryClient.resetQueries() // If we don't remove the queries after invalidating them, the old query data // remains in the cache, casuing a potential privacy issue. diff --git a/waspc/examples/todoApp/prettier.config.js b/waspc/examples/todoApp/prettier.config.js new file mode 100644 index 000000000..abcda7180 --- /dev/null +++ b/waspc/examples/todoApp/prettier.config.js @@ -0,0 +1,6 @@ +module.exports = { + trailingComma: 'es5', + tabWidth: 2, + semi: false, + singleQuote: true, +} diff --git a/waspc/examples/todoApp/src/client/App.jsx b/waspc/examples/todoApp/src/client/App.jsx index 3d4e4162e..319cb6e7a 100644 --- a/waspc/examples/todoApp/src/client/App.jsx +++ b/waspc/examples/todoApp/src/client/App.jsx @@ -1,10 +1,32 @@ +import logout from '@wasp/auth/logout.js' +import useAuth from '@wasp/auth/useAuth.js' + +import './Main.css' + export function App({ children }) { - return ( -
-
-

ToDo App

-
- {children} -
- ); + const { data: user } = useAuth() + + return ( +
+
+

+ ToDo App +

+ {user && ( +
+
+ Hello, {user.username} +
+
+ +
+
+ )} +
+
{children}
+ +
+ ) } diff --git a/waspc/examples/todoApp/src/client/Main.css b/waspc/examples/todoApp/src/client/Main.css index ece746771..f2dd1cc82 100644 --- a/waspc/examples/todoApp/src/client/Main.css +++ b/waspc/examples/todoApp/src/client/Main.css @@ -9,13 +9,17 @@ a { @apply underline text-blue-600 hover:text-blue-800 visited:text-purple-600; } - input[type='submit'] { - @apply btn btn-blue; + input[type="text"], + input[type="password"] { + @apply rounded; + } + input[type="submit"] { + @apply btn btn-primary; } form.auth-form input { @apply my-2; } - input[type='checkbox'] { + input[type="checkbox"] { @apply appearance-none h-4 w-4 border border-gray-300 rounded-sm bg-white checked:bg-blue-600 checked:border-blue-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer; } h1 { @@ -28,15 +32,15 @@ @layer components { .btn { - @apply font-bold py-2 px-4; + @apply font-bold py-2 px-4 rounded; } - .btn-blue { + .btn-primary { @apply bg-blue-500 text-white; } .btn-red { @apply bg-red-500 text-white; } - .btn-blue:hover { - @apply bg-blue-700; + .btn-primary:hover { + @apply bg-blue-600; } } diff --git a/waspc/examples/todoApp/src/client/Todo.tsx b/waspc/examples/todoApp/src/client/Todo.tsx index ec9d1cb17..bb784e703 100644 --- a/waspc/examples/todoApp/src/client/Todo.tsx +++ b/waspc/examples/todoApp/src/client/Todo.tsx @@ -14,23 +14,31 @@ type GetTasksError = { message: string } type NonEmptyArray = [T, ...T[]] -function areThereAnyTasks(tasks: Task[] | undefined): tasks is NonEmptyArray { +function areThereAnyTasks( + tasks: Task[] | undefined +): tasks is NonEmptyArray { return !!(tasks && tasks.length > 0) } const Todo = () => { - const { data: tasks, isError, error: tasksError } = useQuery<{}, Task[], GetTasksError>(getTasks) + const { + data: tasks, + isError, + error: tasksError, + } = useQuery<{}, Task[], GetTasksError>(getTasks) const TasksError = () => { - return
{'Error during fetching tasks: ' + (tasksError?.message || '')}
+ return ( +
{'Error during fetching tasks: ' + (tasksError?.message || '')}
+ ) } return ( -
-
+
+

Todos

-
+
@@ -50,8 +58,8 @@ const Todo = () => { } const Footer = ({ tasks }: { tasks: NonEmptyArray }) => { - const numCompletedTasks = tasks.filter(t => t.isDone).length - const numUncompletedTasks = tasks.filter(t => !t.isDone).length + const numCompletedTasks = tasks.filter((t) => t.isDone).length + const numUncompletedTasks = tasks.filter((t) => !t.isDone).length const handleDeleteCompletedTasks = async () => { try { @@ -62,10 +70,8 @@ const Footer = ({ tasks }: { tasks: NonEmptyArray }) => { } return ( -
-
- {numUncompletedTasks} items left -
+
+
{numUncompletedTasks} items left
+ ) } @@ -181,7 +195,7 @@ const ToggleAllTasksButton = ({ disabled }: { disabled: boolean }) => { return ( - - - ) + return } export default Main diff --git a/waspc/examples/todoApp/src/client/pages/ProfilePage.tsx b/waspc/examples/todoApp/src/client/pages/ProfilePage.tsx index 704aa4426..522f4719d 100644 --- a/waspc/examples/todoApp/src/client/pages/ProfilePage.tsx +++ b/waspc/examples/todoApp/src/client/pages/ProfilePage.tsx @@ -2,12 +2,15 @@ import React from 'react' import { Link } from 'react-router-dom' import { User } from '@wasp/entities' -export const ProfilePage = ({ username }: User) => { +export const ProfilePage = ({ user: { username } }: { user: User }) => { return ( <> -
I am Profile page for { username }!
-
- Go to dashboard +

Profile page

+
+ Hello {username}! +
+
+ Go to dashboard ) }