diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index d925f70..ecefd6f 100755 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: [ 16 ] + node: [ 20 ] steps: - uses: actions/checkout@v3 diff --git a/README.md b/README.md index ea1bfcb..7ca5c99 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,13 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). ## Getting Started -First, run the development server: +Requires `nodejs` version 18 or higher + +1) After cloning, run `npm install` to install dependencies +2) Generate documentation +- For dummy content run `npm run dummy_docs` OR +- For actual content see "Generating versioned documentation" below +3) Start the development server: ```bash npm run dev @@ -16,23 +21,6 @@ Open [http://localhost:3000](http://localhost:3000) with your browser to see the You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. - ## Generating versioned documentation Clone documentation repos in parallel folders next to this one @@ -40,8 +28,23 @@ Clone documentation repos in parallel folders next to this one 1) clone https://github.com/oskariorg/oskari-documentation -> (Should be found in `../oskari-documentation`) 2) clone https://github.com/oskariorg/oskari-frontend -> (Should be found in `../oskari-frontend`) 3) clone https://github.com/oskariorg/oskari-server -> (Should be found in `../oskari-server`) -4) Run `npm run docs [version]` where `[version]` is like `2.13.0` +4) Run `npm run docs [version] [bln_latest]` where: +- `[version]` is like `2.13.0` (defaults to unreleased) +- `[bln_latest]` is like `true` (defaults to false) This: - shovels in everything under `oskari-documentation` to `_content/docs/[version]/` - copies `ReleaseNotes.md` and `api/CHANGELOG.md` to `_content/docs/[version]/[ordinal] Changelog/` + +## Learn More + +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! diff --git a/app/blog/blogPageNavigationComponent.tsx b/app/blog/blogPageNavigationComponent.tsx new file mode 100644 index 0000000..76bd066 --- /dev/null +++ b/app/blog/blogPageNavigationComponent.tsx @@ -0,0 +1,92 @@ +import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/20/solid'; +import { useSearchParams } from 'next/navigation'; +import React, { useCallback } from 'react'; + +export const BLOG_POSTS_PER_PAGE = 9 +interface NavigationComponentProps { + currentPage: number; + totalPages: number; + totalPosts: number; + handleSetPage: (currentPage: number, queryString: string) => void; + paginatedPostsLength: number; +}; + +export default function BlogPageNavigationComponent({ handleSetPage, currentPage, totalPages, totalPosts, paginatedPostsLength }: NavigationComponentProps) { + const searchParams = useSearchParams()! + const createQueryString = useCallback( + (name: string, value: string) => { + const params = new URLSearchParams(searchParams) + params.set(name, value) + + return params.toString() + }, + [searchParams] + ) + + const pageNumbers = Array.from( + { length: totalPages }, + (_, index) => index + 1 + ) + + return <> + +
+ {paginatedPostsLength > 0 + ? `Showing ${(currentPage - 1) * BLOG_POSTS_PER_PAGE + 1} to ${Math.min( + currentPage * BLOG_POSTS_PER_PAGE, + totalPosts + )} of ${totalPosts} posts` + : 'No entries to display'} +
+ ; +} \ No newline at end of file diff --git a/app/blog/page.tsx b/app/blog/page.tsx index 7181352..5a6b00e 100644 --- a/app/blog/page.tsx +++ b/app/blog/page.tsx @@ -3,15 +3,14 @@ import allPosts from '@/_content/blog/'; import Card from '@/components/Cards/Card'; import Layout from '@/components/Layout'; import styles from '@/styles/blog.module.scss'; -import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/20/solid'; -import { usePathname, useRouter, useSearchParams } from 'next/navigation'; -import { useCallback } from 'react' - +import { usePathname, useRouter } from 'next/navigation'; +import BlogPageNavigationComponent, { BLOG_POSTS_PER_PAGE } from './blogPageNavigationComponent'; +import { Suspense, useState } from 'react'; export default function BlogsPage() { const router = useRouter() const pathname = usePathname() - const searchParams = useSearchParams()! + const [page, setPage] = useState('1'); const posts = allPosts.map((post) => { const image = post?.image ? post.image : (post?.imagesFromPost && post.imagesFromPost.length) > 0 ? @@ -27,34 +26,18 @@ export default function BlogsPage() { return item }).sort((a, b) => b.date.getTime() - a.date.getTime()) - const createQueryString = useCallback( - (name: string, value: string) => { - const params = new URLSearchParams(searchParams) - params.set(name, value) - - return params.toString() - }, - [searchParams] - ) - - const POSTS_PER_PAGE = 9 - - const page = searchParams.get('page') || '1' const currentPage = parseInt(page) - const totalPages = Math.ceil(posts?.length / POSTS_PER_PAGE) + const totalPages = Math.ceil(posts?.length / BLOG_POSTS_PER_PAGE) const paginatedPosts = posts?.slice( - (currentPage - 1) * POSTS_PER_PAGE, - currentPage * POSTS_PER_PAGE + (currentPage - 1) * BLOG_POSTS_PER_PAGE, + currentPage * BLOG_POSTS_PER_PAGE ) - const handleSetPage = (page: number) => { - router.push(`${pathname}?${createQueryString('page', page.toString())}`) + const handleSetPage = (currentPage: number, queryString: string) => { + setPage('' + currentPage); + router.push(`${pathname}?${queryString}`) } - const pageNumbers = Array.from( - { length: totalPages }, - (_, index) => index + 1 - ) return ( @@ -62,66 +45,15 @@ export default function BlogsPage() {
{paginatedPosts?.map((item) => )}
- -
- {paginatedPosts && paginatedPosts.length > 0 - ? `Showing ${(currentPage - 1) * POSTS_PER_PAGE + 1} to ${Math.min( - currentPage * POSTS_PER_PAGE, - posts.length - )} of ${posts.length} posts` - : 'No entries to display'} -
+ + +
) } diff --git a/app/discover/gettingstarted/page.tsx b/app/discover/gettingstarted/page.tsx index cf26d77..80aea68 100644 --- a/app/discover/gettingstarted/page.tsx +++ b/app/discover/gettingstarted/page.tsx @@ -10,7 +10,7 @@ export const metadata: Metadata = { export default function GettingStartedPage() { return ( - +
This site contains all the relevant links for finding the information you need about Oskari. The material has been divided under different user groups and customed to their needs. diff --git a/app/documentation/api/bundles/[version]/[slug]/page.tsx b/app/documentation/api/bundles/[version]/[slug]/page.tsx index c5725f9..e41b862 100644 --- a/app/documentation/api/bundles/[version]/[slug]/page.tsx +++ b/app/documentation/api/bundles/[version]/[slug]/page.tsx @@ -29,6 +29,5 @@ export default async function BundlesContentPage({ version={params.version} sideBarContent={} mainContent={} - title='Oskari API documentation' baseHref='/documentation/api/bundles/'/>; } diff --git a/app/documentation/api/bundles/[version]/page.tsx b/app/documentation/api/bundles/[version]/page.tsx index 4820856..8fabfa6 100644 --- a/app/documentation/api/bundles/[version]/page.tsx +++ b/app/documentation/api/bundles/[version]/page.tsx @@ -15,6 +15,5 @@ export default async function BundlesVersionPage({ version={params.version} sideBarContent={} mainContent={} - title='Oskari API documentation' baseHref='/documentation/api/bundles/'/>; } diff --git a/app/documentation/api/bundles/layout.tsx b/app/documentation/api/bundles/layout.tsx new file mode 100644 index 0000000..946f453 --- /dev/null +++ b/app/documentation/api/bundles/layout.tsx @@ -0,0 +1,15 @@ +import DefaultLayout from '@/components/Layout' +import { Suspense } from 'react' +import Loading from '../../docs/loading' + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( + +
+
+ }>{children} +
+
+
+ ) +} diff --git a/app/documentation/api/components/ApiDocsLayout.tsx b/app/documentation/api/components/ApiDocsLayout.tsx new file mode 100644 index 0000000..8bf437b --- /dev/null +++ b/app/documentation/api/components/ApiDocsLayout.tsx @@ -0,0 +1,20 @@ +import DefaultLayout from '@/components/Layout' +import { Suspense } from 'react' +import Loading from '../../docs/loading' + +/** + * This way is "wrong". We should instead use layout in a more orderly nextjs fashion + * This will need some refactoring at some point. This is just a quick and dirty solution + * to make app work just like before even after migration to nextjs 14 + */ +export default function ApiDocsLayout({ children }: { children: React.ReactNode }) { + return ( + +
+
+ }>{children} +
+
+
+ ) +} diff --git a/app/documentation/api/components/ApiSectionContentPage.tsx b/app/documentation/api/components/ApiSectionContentPage.tsx index f5bfb73..feae568 100644 --- a/app/documentation/api/components/ApiSectionContentPage.tsx +++ b/app/documentation/api/components/ApiSectionContentPage.tsx @@ -2,16 +2,13 @@ import VersionSidebar from '@/components/VersionSidebar'; import { compareSemanticVersions } from '@/utils/misc'; import availableVersions from '_content/api/versions' -import Layout from '../../docs/layout'; import { ReactNode } from 'react'; export default function ApiSectionContentPage({ - title, sideBarContent, mainContent, baseHref, version }: { - title: string, sideBarContent: ReactNode, mainContent: ReactNode, baseHref: string, @@ -25,7 +22,7 @@ export default function ApiSectionContentPage({ ), ]; - return + return <>
{sideBarContent} @@ -33,5 +30,5 @@ export default function ApiSectionContentPage({
{mainContent}
- ; + ; } diff --git a/app/documentation/api/events/[version]/[slug]/page.tsx b/app/documentation/api/events/[version]/[slug]/page.tsx index 4a402a7..d7aa916 100644 --- a/app/documentation/api/events/[version]/[slug]/page.tsx +++ b/app/documentation/api/events/[version]/[slug]/page.tsx @@ -30,6 +30,5 @@ export default async function EventsContentPage({ version={params.version} sideBarContent={} mainContent={} - title='Oskari API documentation' baseHref='/documentation/api/events/'/>; } diff --git a/app/documentation/api/events/[version]/page.tsx b/app/documentation/api/events/[version]/page.tsx index 6d2d2e7..5d80e14 100644 --- a/app/documentation/api/events/[version]/page.tsx +++ b/app/documentation/api/events/[version]/page.tsx @@ -15,6 +15,5 @@ export default async function EventsVersionPage({ version={params.version} sideBarContent={} mainContent={} - title='Oskari API documentation' baseHref='/documentation/api/events/'/>; } diff --git a/app/documentation/api/events/layout.tsx b/app/documentation/api/events/layout.tsx new file mode 100644 index 0000000..946f453 --- /dev/null +++ b/app/documentation/api/events/layout.tsx @@ -0,0 +1,15 @@ +import DefaultLayout from '@/components/Layout' +import { Suspense } from 'react' +import Loading from '../../docs/loading' + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( + +
+
+ }>{children} +
+
+
+ ) +} diff --git a/app/documentation/api/page.tsx b/app/documentation/api/page.tsx index cce98bb..3c684dc 100644 --- a/app/documentation/api/page.tsx +++ b/app/documentation/api/page.tsx @@ -4,8 +4,7 @@ import DefaultLayout from "@/components/Layout"; import Text from '@/components/Text' export default function ApiMainPage() { - return <> - + return Oskari API is defined as bundles. Bundle is a definition of functionality that may provide external API to control the functionality. @@ -40,6 +39,5 @@ export default function ApiMainPage() {
- - ; + ; } diff --git a/app/documentation/api/requests/[version]/[slug]/page.tsx b/app/documentation/api/requests/[version]/[slug]/page.tsx index 27b55d5..cb77075 100644 --- a/app/documentation/api/requests/[version]/[slug]/page.tsx +++ b/app/documentation/api/requests/[version]/[slug]/page.tsx @@ -29,6 +29,5 @@ export default async function RequestsContentPage({ version={params.version} sideBarContent={} mainContent={} - title='Oskari API documentation' baseHref='/documentation/api/requests/'/>; } diff --git a/app/documentation/api/requests/[version]/page.tsx b/app/documentation/api/requests/[version]/page.tsx index 08731c5..4b7f665 100644 --- a/app/documentation/api/requests/[version]/page.tsx +++ b/app/documentation/api/requests/[version]/page.tsx @@ -15,6 +15,5 @@ export default async function RequestsVersionPage({ version={params.version} sideBarContent={} mainContent={} - title='Oskari API documentation' baseHref='/documentation/api/requests/'/>; } diff --git a/app/documentation/api/requests/layout.tsx b/app/documentation/api/requests/layout.tsx new file mode 100644 index 0000000..946f453 --- /dev/null +++ b/app/documentation/api/requests/layout.tsx @@ -0,0 +1,15 @@ +import DefaultLayout from '@/components/Layout' +import { Suspense } from 'react' +import Loading from '../../docs/loading' + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( + +
+
+ }>{children} +
+
+
+ ) +} diff --git a/app/documentation/docs/layout.tsx b/app/documentation/docs/layout.tsx index b64c7c0..6b4ddc4 100644 --- a/app/documentation/docs/layout.tsx +++ b/app/documentation/docs/layout.tsx @@ -2,9 +2,9 @@ import DefaultLayout from '@/components/Layout' import { Suspense } from 'react' import Loading from './loading' -export default function Layout({ children, heroTitle = 'Documentation' }: { children: React.ReactNode, heroTitle: string }) { +export default function Layout({ children }: { children: React.ReactNode }) { return ( - +
}>{children} diff --git a/components/Layout.tsx b/components/Layout.tsx index 805117b..ba0e9c9 100644 --- a/components/Layout.tsx +++ b/components/Layout.tsx @@ -5,19 +5,21 @@ import Navigation from '@/components/Navigation/Navigation' interface LayoutProps { children: React.ReactNode heroSmall?: boolean - heroTitle?: string + heroTitle?: string, + decorateLinks?: boolean } export default function Layout({ children, heroSmall = false, heroTitle = 'Oskari – a mapping tool that adapts to your needs', + decorateLinks = false }: LayoutProps) { return ( <> -
{children}
+
{children}