V1 without presentation styling

This commit is contained in:
Daniel Heras Quesada committed 2024-01-16 23:53:33 +01:00
1 parent 39705a7b43
commit 3869d67172
295 files changed
+375 -1252

No files matched your search

@@ -1,16 +0,0 @@
import { getRandomWordList } from "@/words/word-list/utils";
const getServerSideProps = async () => {
const wordList = await getRandomWordList();
console.log("Data is being fetch...", wordList)
return { props: { wordList:wordList } }
}
export default async function WordList(){
const wordList = await getServerSideProps();
return (
<div data-testid="word-list-view">
WordList server props: {JSON.stringify(wordList)}
</div>
)
}
@@ -1 +0,0 @@
export * from './word-list.view'
@@ -1,15 +0,0 @@
import { WordListRepsonse } from './word-list.types'
const dataURL = 'http://localhost:3000/words/es?complexity=easy&howMany=10'
export async function getStaticProps() {
const randomWordList = await getRandomWordList();
return {
props: { randomWordList }, // will be passed to the page component as props
}
}
export async function getRandomWordList() {
const wordList: WordListRepsonse = await fetch(dataURL).then((response) => response.json());
return wordList;
}
@@ -1,3 +0,0 @@
.container {
}
@@ -1,23 +0,0 @@
import type { Meta, StoryObj } from '@storybook/react'
import { expect } from '@storybook/jest'
import { within } from '@storybook/testing-library'
import { WordListView } from './word-list.view'
const meta: Meta<typeof WordListView> = {
title: 'WordListView',
component: WordListView,
argTypes: {},
}
export default meta
type Story = StoryObj<typeof WordListView>
export const Default: Story = {
args: {},
async play({ canvasElement }) {
const canvas = within(canvasElement)
const container = canvas.getByTestId('word-list-view')
expect(container).toBeTruthy()
},
}
@@ -1,8 +0,0 @@
export type WordElement = {
word: string
correct?: boolean
}
export type WordListRepsonse = {
wordList: WordElement[]
}
@@ -1,15 +0,0 @@
import React from 'react'
import styles from './word-list.module.css'
import { InferGetServerSidePropsType, InferGetStaticPropsType } from 'next'
import { getRandomWordList, getStaticProps } from './utils'
export function WordListView(
props: InferGetStaticPropsType<typeof getStaticProps>
) {
return (
<div data-testid="word-list-view" className={styles.container}>
WordList: {JSON.stringify(props?.randomWordList)}
</div>
)
}
@@ -1,5 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import url('https://fonts.googleapis.com/css2?family=Lexend:wght@100;200;300;400;500;600;700;800;900&display=swap');
Submodule examples/front-arch-ssr-react deleted from febdeb7828.
@@ -1,15 +0,0 @@
# Generated files
node_modules
output
dist
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
File diff suppressed because it is too large. Load diff
@@ -1,20 +0,0 @@
{
"name": "presentation-animations",
"private": true,
"version": "0.0.0",
"scripts": {
"serve": "vite",
"build": "tsc && vite build"
},
"dependencies": {
"@motion-canvas/core": "^3.11.0",
"@motion-canvas/2d": "^3.11.0",
"@motion-canvas/ffmpeg": "^1.1.0"
},
"devDependencies": {
"@motion-canvas/ui": "^3.11.0",
"@motion-canvas/vite-plugin": "^3.11.0",
"typescript": "^4.9.5",
"vite": "^4.1.4"
}
}
@@ -1 +0,0 @@
/// <reference types="@motion-canvas/core/project" />
@@ -1,32 +0,0 @@
{
"version": 0,
"shared": {
"background": null,
"range": [
0,
null
],
"size": {
"x": 1920,
"y": 1080
},
"audioOffset": 0
},
"preview": {
"fps": 30,
"resolutionScale": 1
},
"rendering": {
"fps": 60,
"resolutionScale": 1,
"colorSpace": "srgb",
"exporter": {
"name": "@motion-canvas/core/image-sequence",
"options": {
"fileType": "image/png",
"quality": 100,
"groupByScene": false
}
}
}
}
@@ -1,7 +0,0 @@
import {makeProject} from '@motion-canvas/core';
import example from './scenes/example?scene';
export default makeProject({
scenes: [example],
});
@@ -1,5 +0,0 @@
{
"version": 0,
"timeEvents": [],
"seed": 1375832605
}
@@ -1,22 +0,0 @@
import {makeScene2D, Circle} from '@motion-canvas/2d';
import {all, createRef} from '@motion-canvas/core';
export default makeScene2D(function* (view) {
const myCircle = createRef<Circle>();
view.add(
<Circle
ref={myCircle}
// try changing these properties:
x={-300}
width={140}
height={140}
fill="#e13238"
/>,
);
yield* all(
myCircle().position.x(300, 1).to(-300, 1),
myCircle().fill('#e6a700', 1).to('#e13238', 1),
);
});
@@ -1,4 +0,0 @@
{
"extends": "@motion-canvas/2d/tsconfig.project.json",
"include": ["src"]
}
@@ -1,10 +0,0 @@
import {defineConfig} from 'vite';
import motionCanvas from '@motion-canvas/vite-plugin';
import ffmpeg from '@motion-canvas/ffmpeg';
export default defineConfig({
plugins: [
motionCanvas(),
ffmpeg(),
],
});
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,6 +1,9 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
reactStrictMode: true, reactStrictMode: true,
experimental: {
serverActions: true,
},
// Avoiding CORS issues // Avoiding CORS issues
// async rewrites() { // async rewrites() {
// return [ // return [
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+140
View File
@@ -0,0 +1,140 @@
'use client'
import { useRouter } from 'next/navigation'
import { useState } from 'react'
export default function Presentation() {
const [current, setCurrent] = useState<number>(0)
const stages = [
<Introduction />,
<Benefits />,
<Rendering />,
<Strategies />,
<DataFetching />,
]
return (
<div className="main-presentation">
{stages[current]}
<button
onClick={() =>
setCurrent(current + 1 < stages.length ? current + 1 : 0)
}
>
Siguiente
</button>
</div>
)
}
// 1. Introduction
// 2. Rendering strategies.
// 3. Benefits.
// 4. Actual process and why its important to know it.
// 5. Serverside data fetching
function Introduction() {
return (
<div className="main-presentation-comparation">
<h3>Next</h3>
<div>
<p>Nos da la posibilidad de renderizar desde el servidor</p>
</div>
</div>
)
}
function Rendering() {
return (
<div className="main-presentation-comparation">
<h3>Rendering</h3>
<div>
The rendering works is split into chunks: - By individual route
segments - By React [Suspense
boundaries](https://react.dev/reference/react/Suspense) (react
way of having a fallback while a components has finished
loading) Each chunk is rendered in the server, then, on the
client: 1. The HTML is used to immediately show fast preview. 2.
The server components rendered are inserted to update the DOM
(components rendered in server with placeholders for client
components and props). 3. `JS` instructions are used to
[hydrate?](https://react.dev/reference/react-dom/client/hydrateRoot)
Client Components and make the application interactive.
</div>
</div>
)
}
function Strategies() {
return (
<div className="main-presentation-strategies">
<h3>Strategies</h3>
<div>
<ul>
<li>
- Static rendering (default): Good for static pages:
Rendered in build time or in the background after data
revalidation
</li>
<li>
- Security: sensitive data is kept int the server (API
keys and tokens)
</li>
<li>
- Dynamic rendering: rendered per user request, Next
uses this type of rendering automatically when discovers
a dynamic function (`cookies()`, `headers()`,
`userSearchParams()`).
</li>
<li>
- Streaming: work is split into chunks and streamed as
they become ready so the load is progressive.
</li>
</ul>
</div>
</div>
)
}
function Benefits() {
return (
<div className="main-presentation-benefits">
<h3>Beneficios</h3>
<div>
<ul>
<li>
- Fetch data directly on the server, performance and
load benefits.
</li>
<li>
- Security: sensitive data is kept int the server (API
keys and tokens)
</li>
<li>
- Caching: results can be cached to improve performance
between users.
</li>
<li>
- Bundle size: will be reduced as part of the
application will reside in the server.
</li>
<li>
- SEO: because the pages will be rendered the search
engine bots will make good use of it.
</li>
<li>
- Streaming: to split the rendering into chunks and
stream them as they become ready.
</li>
</ul>
</div>
</div>
)
}
function DataFetching() {
const router = useRouter()
router.push('/word-list')
return <>Redirecting...</>
}
@@ -0,0 +1,6 @@
'use server'
import { revalidateTag } from 'next/cache'
export async function revalidateFetchByTag(tag: string) {
revalidateTag(tag)
}
@@ -0,0 +1,31 @@
'use client'
import { useEffect, useState } from 'react'
import { WordListRepsonse, fetchWordlist } from '../utils'
export default function ClientWordList() {
const [data, setData] = useState<WordListRepsonse>()
const fetchData = () =>
fetchWordlist().then((response) => setData(response))
useEffect(() => {
fetchData()
}, [])
return (
<div className="data-fetching-client">
<h3>
Wordlist fetched in the <span>client</span>
</h3>
<div>
{data?.wordList.map((word) => (
<span>{word.word}</span>
))}
</div>
<div>
<button onClick={fetchData}>Revalidate!</button>
</div>
</div>
)
}
@@ -0,0 +1,15 @@
'use client'
import { useRouter } from 'next/navigation'
export default function GoBackButton() {
const router = useRouter()
return (
<button
style={{ position: 'absolute' }}
onClick={() => router.push('/presentation')}
>
Go back to presentation
</button>
)
}
@@ -0,0 +1,11 @@
'use client'
import { revalidateFetchByTag } from '../actions'
export default function RevalidateButton() {
return (
<button onClick={() => revalidateFetchByTag('wordlist')}>
Revalidate!
</button>
)
}
@@ -0,0 +1,22 @@
import RevalidateButton from './revalidate-button'
import { fetchWordlist } from '../utils'
export default async function ServerWordList() {
const response = await fetchWordlist()
return (
<div data-testid="word-list-view" className="data-fetching-server">
<h3>
Wordlist fetched in the <span>server</span>
</h3>
<div>
{response?.wordList.map((word) => (
<span>{word.word}</span>
))}
</div>
<div>
<RevalidateButton />
</div>
</div>
)
}
+12
View File
@@ -0,0 +1,12 @@
import ClientWordList from './components/clientside-word-list'
import GoBackButton from './components/go-back-button'
import ServerWordList from './components/serverside-word-list'
export default function WordList() {
return (
<div className="data-fetching">
<ServerWordList />
<ClientWordList />
</div>
)
}
+22
View File
@@ -0,0 +1,22 @@
const WORDLIST_API_URL =
'http://localhost:3000/words/es?complexity=medium&howMany=30'
export type WordElement = {
word: string
correct?: boolean
}
export type WordListRepsonse = {
wordList: WordElement[]
}
// fetch("https://...", { cache: "no-store" });
export const fetchWordlist = async () => {
const wordList: WordListRepsonse = await fetch(WORDLIST_API_URL, {
next: { tags: ['wordlist'] },
}).then((response) => response.json())
console.log('Data fetch is done', wordList)
return wordList
}
Loaded 100 of 295 files, more files were not shown because too many files have changed in this diff. Show more