wrjlewis / notion-search-alfred-workflow

An Alfred workflow to search Notion with instant results
GNU General Public License v3.0
828 stars 41 forks source link

Having "In page" Notion Quick Search Option implemented into the Notion Search Alfred Workflow ? #65

Open daemuu opened 1 year ago

daemuu commented 1 year ago

Hi Will @wrjlewis,

I just managed to make the workflow working after installing Command Line Tools on my Mac, and now it works like a charm ! 🙏 I have a regular use case where i would need to search only in a specific main page/database i have, without getting "noised" by the others.

Thus, I was wondering if there is currently a way to use the workflow with an equivalent of the "In page" Quick Search option available into Notion ? If not do you think that would be something you could do as a future improvement please ?

Maybe it could be through the setup of a new environnement variable (as you did with the "Only search titles" and the isNavigableOnly variable) ; or maybe it could be through a kind a modifier key allowing this "In (this) page" search on the one we would have selected through the regular "ns" search feature ?

What do you think about this ? Is it manageable, code wise, according to you ?

Have a good one, D.

wrjlewis commented 1 year ago

Hi,

I'm not sure if it's possible but it's a good idea and one we can add to the list here and see if folk would be interested.

I suspect it's not a small change and would involve another call to Notion to get the data, so unlikely I'll get around to making this feature in the foreseeable but I'll try and find some time to scope it out at least.

Thanks

daemuu commented 1 year ago

Hi will, thanks for your feedback : i will wait, watch and see then ! :)

svenko99 commented 1 year ago

Hi,

This can be achived by adding page ID or database ID of the main page or database to the "ancestors" in "filters" in the query. For example:

def buildnotionsearchquerydata():
    query = {}
    query["type"] = "BlocksInSpace"
    query["query"] = alfredQuery
    query["spaceId"] = notionSpaceId
    query["limit"] = 9
    filters = {}
    filters["isDeletedOnly"] = False
    filters["excludeTemplates"] = False
    filters["isNavigableOnly"] = isNavigableOnly
    filters["navigableBlockContentOnly"] = isNavigableOnly
    filters["requireEditPermissions"] = False
->  ancestors = ["3f8b5fe7-13a4-4b1e-b436-dgfd9d63c587"]
    filters["ancestors"] = ancestors
    createdby = []
    filters["createdBy"] = createdby
    editedby = []
    filters["editedBy"] = editedby
    lasteditedtime = {}
    filters["lastEditedTime"] = lasteditedtime
    createdtime = {}
    filters["createdTime"] = createdtime
    query["filters"] = filters
    query["sort"] = "Relevance"
    query["source"] = "quick_find_input_change"
wrjlewis commented 1 year ago

Getting closer, thanks @svenko99 , just need to understand or see an example ideally of how this can be set up as a key modifier on an existing search result

svenko99 commented 1 year ago

how this can be set up as a key modifier on an existing search result

Do you mean that when a user presses a modifier key within an existing search result, it will display only the selected pages to the user?

What about a new environment variable? Users would simply provide a link to the main page(s), and the script would automatically extract the ID of the specified page(s).

wrjlewis commented 1 year ago

I mean I think it would be good if you can select the page from search results, then press tab or something, that would open a new search box that would only search within that specific page. Rather than having to find a page id yourself and manually put it in as a configuration variable, which would mean you could only ever search within that page unless you updated the config variable again.

On Fri, 16 Jun 2023 at 19:13, svenko99 @.***> wrote:

how this can be set up as a key modifier on an existing search result

Do you mean that when a user presses a modifier key within an existing search result, it will display only the selected pages to the user?

What about a new environment variable? Users would simply provide a link to the main page(s), and the script would automatically extract the ID of the specified page(s).

— Reply to this email directly, view it on GitHub https://github.com/wrjlewis/notion-search-alfred-workflow/issues/65#issuecomment-1595089052, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALY3SRWPAGZ3I2QXZ3Y57LXLSO5RANCNFSM6AAAAAARMHWQXU . You are receiving this because you were mentioned.Message ID: @.***>

svenko99 commented 1 year ago

I have remade the workflow, incorporating a new feature that allows searching within a page. The functionality is showcased in the video that is attached to the link. To utilize searching within a page, simply press the Tab key to autocomplete the page name (in Alfred), followed by the space to initiate the search within the page.

Here is the link to the workflow and the video: https://easyupload.io/m/v36ytw

Feel free to take a look at it if you're interested. Any criticism is welcomed.

wrjlewis commented 1 year ago

Hey @svenko99, thanks for sharing! Really appreciate it. Could you please explain a bit about how it works?

When you press tab it autocompletes the page name, then you enter a new word(s) to search within the page. What is the query string that gets sent to notion, is it just "[page name] + [new word(s)]", right? I'm not sure how thats different to how the workflow works today. Or are there other changes / things going on?

svenko99 commented 1 year ago

So in the utils.py there is a function that converts title of Notion page to its page ID if it exists:

def title_to_id(record_map, title_to_find):
    collection = record_map.get("collection")
    for block in record_map["block"].values():
        block = block["value"]
        if block.get("type") == "page":
            title = block["properties"]["title"][0][0]
            if title == title_to_find:
                return block["id"]

        elif block.get("type") == "collection_view_page":
            collection_pointer_id = block["format"]["collection_pointer"]["id"]
            title = collection[collection_pointer_id]["value"]["name"][0][0]
            if title == title_to_find:
                return block["id"]
    return None

For example if I type in Alfred Links UX, this piece of code in parse_data.py:

if __name__ == "__main__":
    try:
        if ALFRED_QUERY == "":
            items = scrape_recently_viewed_pages(get_data(type="recent"))
        else:
            data = get_data(type="search", query=ALFRED_QUERY)
            if page_id := title_to_id(
                data["recordMap"], ALFRED_QUERY.split()[0].replace("_", " ")
            ):
                items = scrape_search_results(
                    get_data(
                        type="search",
                        # here we remove the first word from the query. For example, if the query is "Links query", we remove "Links" and search for "query"
                        query=" ".join(ALFRED_QUERY.split()[1:]),
                        ancestors=[page_id],
                    )
                )
            else:
                items = scrape_search_results(data)

        print(output_results(items))

    except UnboundLocalError as e:
       ...

will check if the first word (Links) is a page/database and it will add the ID of the page/database do the ancestors if there is an ID. The first word (Links) will be removed from the query, so the query will look like "UX".

Also ALFRED_QUERY.split()[0].replace("_", " ") is necessary because when pressing tab to autocomplete the page that has spaces, the page will be autocompleted like this (More links -> More_links) so we must change it to its normal state (More links).

Here is the updated version of this implementation: https://easyupload.io/ua84zz

If you have any more questions, feel free to ask!

wrjlewis commented 1 year ago

Hey

Nice! Just a question, if I had a database called actions but also a page called actions from last meeting, would the functionality above presume I'm searching the database if I typed actions from last meeting? And therefore I'd miss out on the search result I really wanted, in that example. Or am I misunderstanding?

svenko99 commented 1 year ago

Good observation! Here the user would have to press ⇥ tab to autocomplete the page actions from last meeting (so it would become: actions_from_last_meeting). Or the user would have to type "_" instead of a spaces.

Here is a GIF showing the above action.

I am aware that this is not an ideal solution. Do you have any suggestions on how we can improve this process?

wrjlewis commented 1 year ago

Got it, understood. I think it's a great bit of functionality and nicely done.

It's a shame there isn't a more clean way of doing this, on Alfred's side, that makes the above more convenient. Though I think you've probably got the best solution given the tool's constraints.

Just thinking out loud, would be nice if you could scroll down to a page in a search result, press shift +enter or something like that, which sends you to a new script filter that makes it obvious you're now searching within that page. Only downside is that when you want to do a normal notion-wide search again, you'd have to close and start a new search.

svenko99 commented 1 year ago

Just thinking out loud, would be nice if you could scroll down to a page in a search result, press shift +enter or something like that, which sends you to a new script filter that makes it obvious you're now searching within that page. Only downside is that when you want to do a normal notion-wide search again, you'd have to close and start a new search.

Yeah, I was thinking in the same lines, but couldn't find a solution for this kind of functionality. I can send you a link of my modified version of this workflow (had to make some adjustments, so that everything works), where I implemented searching within a page.

wrjlewis commented 1 year ago

That would be great, thanks. Hope you're having success with your other workflows too, I think you have one using the public notion api, how have you found it so far?

On Wed, 5 Jul 2023 at 14:17, svenko99 @.***> wrote:

Just thinking out loud, would be nice if you could scroll down to a page in a search result, press shift +enter or something like that, which sends you to a new script filter that makes it obvious you're now searching within that page. Only downside is that when you want to do a normal notion-wide search again, you'd have to close and start a new search.

Yeah, I was thinking in the same lines, but couldn't find a solution for this kind of functionality. I can send you a link of my modified version of this workflow (had to make some adjustments, so that everything works), where I implemented searching within a page.

— Reply to this email directly, view it on GitHub https://github.com/wrjlewis/notion-search-alfred-workflow/issues/65#issuecomment-1621740203, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALY3SQVCJKAUFCEABP3ZHTXOVSPLANCNFSM6AAAAAARMHWQXU . You are receiving this because you were mentioned.Message ID: @.***>

svenko99 commented 1 year ago

No problem! Here is a link to download the workflow.

Yeah, I've made Notion workflow using Notion API. I was a bit disappointed to be honest; it's slower than the API used in your workflow. The only thing better is that the data is not all over the place. You get a nice structured JSON response which is easy to parse. Also, there is no option to view recently viewed pages.

wrjlewis commented 1 year ago

Thanks!

Yeah that’s normally the way, tends to be more logic and servers in the way of a proper public API compared to more direct access, hopefully they speed up over time.

Would like to use the public api instead of cookie values for ease of use. My ideal flow would be for a user to oauth for authentication (ie no notion api key management themselves) and with full access to what their notion user has access to without having to select each parent page they want the workflow to be able to search.

OAuth doesn’t fit with the way Alfred workflows are designed as with Oauth you need a server to call back to during registration.

I think what you’ve setup is the best that can be done for now with the public api, just still a bit of a trade off.

It’s a nightmare how the data is structured in the way I’m accessing it 😂

On Thu, 6 Jul 2023 at 18:01, svenko99 @.***> wrote:

No problem! Here is a link https://transfer.sh/FFov7eKzeU/Notion%20Search%20V2.alfredworkflow to download the workflow.

Yeah, I've made Notion workflow using Notion API. I was a bit disappointed to be honest; it's slower than the API used in your workflow. The only thing better is that the data is not all over the place. You get a nice structured JSON response which is easy to parse. Also, there is no option to view recently viewed pages.

— Reply to this email directly, view it on GitHub https://github.com/wrjlewis/notion-search-alfred-workflow/issues/65#issuecomment-1624012144, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALY3SVXX4U6YXLJL5BB52TXO3VO5ANCNFSM6AAAAAARMHWQXU . You are receiving this because you were mentioned.Message ID: @.***>