primocms / primo

Primo is a visual CMS with a built-in code editor, Svelte blocks, and static site generator.
https://primocms.org
MIT License
1.92k stars 474 forks source link

Api additions #375

Closed rallisf1 closed 4 months ago

rallisf1 commented 5 months ago

I went ahead and added what was discussed on #373

Even more efficient page API

You can now get exactly the sections you need via the page API via a query parameter: &sections=id1,id2...

Search endpoint

Fancy a search widget for your primo website that uses no 3rd party search service? So did I! Go crazy with /api/site_url/websearch?q=your search terms

Existing installations need to run the following query in their supabase dashboard:

CREATE OR REPLACE FUNCTION page_search(search_terms text, site_url text)
RETURNS TABLE(id uuid, name text, url text, created_at timestamp with time zone) AS $$
BEGIN
    RETURN QUERY
    WITH RECURSIVE parent_urls AS (
        SELECT
            p.id,
            ARRAY[p.url] AS urls
        FROM pages p
        INNER JOIN sites s ON p.site = s.id 
        WHERE p.parent IS NULL AND s.url = site_url

        UNION ALL

        SELECT
            p.id,
            pu.urls || p.url
        FROM pages p
        INNER JOIN sites s ON p.site = s.id 
        INNER JOIN parent_urls pu ON p.parent = pu.id
        WHERE s.url = site_url
    )
    SELECT DISTINCT
        p.id,
        p.name,
        ARRAY_TO_STRING(parent_urls.urls, '/', '/') AS url,
        p.created_at
    FROM pages p
    INNER JOIN sites s ON p.site = s.id
    INNER JOIN sections se ON p.id = se.page
    INNER JOIN parent_urls ON p.id = parent_urls.id
    WHERE s.url = site_url AND to_tsvector(se.content) @@ to_tsquery(search_terms);
END;
$$ LANGUAGE plpgsql;

P.S. Since most people use search for their search results page url I thought websearch would be the next best candidate. Feel free to change it.

P.S.2. I couldn't figure out a better way to get the full url of the result posts. Any improvements are welcome.

mateomorris commented 5 months ago

Nice! Will review this week. What do you think of just a search param instead of /websearch?q? That way we wouldn't have to worry about /websearch resembling a page endpoint, and you could run a search against the whole site, or a specific page.

Like: /api/site_url?search=your search terms or /api/site_url/page_url?search=your search terms Searching only within a page's subpages could be useful for things like searching blog posts

rallisf1 commented 5 months ago

Separate endpoints keep the code cleaner. We can still add parent_url query param to limit the search on subpages.

It's your baby though, so as long as it can still do a whole site search I don't really mind :D

mateomorris commented 4 months ago

Okay thanks - switched to using a query param isntead and exported the page_search function to keep things clean. I tried modifying it to work on pages but couldn't finish, so that'll have to wait for another day.

Besides that, I also fixed an issue with fetching from root pages (sections was showing up empty) - caused by querying select('page(parent!inner(url)' when parent is null.