Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 4 Planning #2678

Closed
patrick-rodgers opened this issue May 15, 2023 · 29 comments
Closed

Version 4 Planning #2678

patrick-rodgers opened this issue May 15, 2023 · 29 comments

Comments

@patrick-rodgers
Copy link
Member

patrick-rodgers commented May 15, 2023

Hello!

The PnPjs core team is discussing version 4 of PnPjs. No big changes planned for this go-round, just improvements and lots more coverage for Microsoft Graph.

We'd love to hear from all of you about your love/hate/wish was easier list in v3 to help guide our thinking for v4. The more detail you can share the better so we can understand your idea.

We setup a board so you can view our current thinking.

Please share your feedback as a comment below!

Thanks,

🐇🐇🐇
@bcameron1231, @juliemturner, @patrick-rodgers

@Tanddant
Copy link

Something that would be really cool! - a fluent way to write the filter query

So "title eq 'test'" becomes something like .filter(textField("title").equals("test")) - CamlJS does this awesomely for CAML!

Thanks for all the awesome work you all are doing! 🙌

@juliemturner
Copy link
Collaborator

Something that would be really cool! - a fluent way to write the filter query

So "title eq 'test'" becomes something like .filter(textField("title").equals("test")) - CamlJS does this awesomely for CAML!

Thanks for all the awesome work you all are doing! 🙌

I agree with this idea if it can happen as it would be especially useful to have helper functions here for things like dates...

@Tanddant
Copy link

I agree with this idea if it can happen as it would be especially useful to have helper functions here for things like dates...

Dates, booleans (do you write true/false or 1 and 0), lookups, maybe even things like "in date rage" - also to bring forward some of the lesser known options like startsWith

Loads of awesome potential, but maybe also a bigger undertaking 😊

@patrick-rodgers
Copy link
Member Author

I agree with this idea if it can happen as it would be especially useful to have helper functions here for things like dates...

Dates, booleans (do you write true/false or 1 and 0), lookups, maybe even things like "in date rage" - also to bring forward some of the lesser known options like startsWith

Loads of awesome potential, but maybe also a bigger undertaking 😊

I love this idea, and when it has come up in the past I've suggested it would be a great project for someone to undertake as a separate library. We can def take a look at it in our planning and see where it falls. Thanks for the suggestion!

@bcameron1231 bcameron1231 unpinned this issue Jul 19, 2023
@patrick-rodgers patrick-rodgers pinned this issue Aug 21, 2023
@Ofer-Gal
Copy link

Ofer-Gal commented Oct 2, 2023

Please allow getting and setting lists from any site collection the easy way you had it in version 2... The whole business of changing the context with:
export const getSP = (context?:WebPartContext ): SPFI => { if (_sp === null && context !== null) { _sp = spfi().using(SPFx({ pageContext: context.pageContext })); _context = context; } return _sp; };
Is cumbersome and in 3.18 causes bunch of TypeScript errors about not being null.
We like simple :-)

@Tanddant
Copy link

Tanddant commented Oct 2, 2023

Please allow getting and setting lists from any site collection the easy way you had it in version 2... The whole business of changing the context with: export const getSP = (context?:WebPartContext ): SPFI => { if (_sp === null && context !== null) { _sp = spfi().using(SPFx({ pageContext: context.pageContext })); _context = context; } return _sp; }; Is cumbersome and in 3.18 causes bunch of TypeScript errors about not being null. We like simple :-)

@Ofer-Gal, I tend to just do

const sp = spfi().using(SPFx(this._Context));
const otherSite = spfi(<OtherSiteURL>).using(AssignFrom(sp.web));

Any reason that dosen't work for you?
Gives me access to the current web, but also any other web the user has access to

@juliemturner
Copy link
Collaborator

That's a good one to share @Tanddant ... my preference is below which is the most similar to v2 method.

const web = Web([sp.web, {Other Web URL}]);

Here are all the options: https://pnp.github.io/pnpjs/getting-started/#connect-to-a-different-web

@Ofer-Gal
Copy link

Ofer-Gal commented Oct 2, 2023

@Tanddant I use hooks so this._Context does not exist.
@juliemturner I tried:
const projWeb: IWeb = Web([sp.web, { window.location.origin + "/Teams/" + projectNumber}]);
but TypeScript says:
Argument of type '[any, { window: Window & typeof globalThis; "": string; }]' is not assignable to parameter of type 'SPInit'.
Type '[any, { window: Window & typeof globalThis; "": string; }]' is not assignable to type 'ISPQueryable | [ISPQueryable, string]'.
Type '[any, { window: Window & typeof globalThis; "": string; }]' is not assignable to type '[ISPQueryable, string]'.
Type at position 1 in source is not compatible with type at position 1 in target.
Type '{ window: Window & typeof globalThis; "": string; }' is not assignable to type 'string'.ts(2345)

Where should sp come from?

@Tanddant
Copy link

Tanddant commented Oct 2, 2023

@Ofer-Gal - The second paramater is a string, try:

const projWeb: IWeb = Web([sp.web, `${window.location.origin}/Teams/${projectNumber}`])

As for my solution, the context I'm referencing is the WebPartContext, I've just passed it to my provider class, that's available in the root of your Web Part as this.context, from the sample you have it would just be

const sp = spfi().using(SPFx(context));
const otherSite = spfi(<OtherSiteURL>).using(AssignFrom(sp.web));

Or with @juliemturner's admittedly more sleek approach

const sp = spfi().using(SPFx(context));
const OtherWeb = Web([sp.web, <OtherSiteURL>])

@Ofer-Gal
Copy link

Ofer-Gal commented Oct 3, 2023

Works great thanks!

@Tanddant
Copy link

@juliemturner or @patrick-rodgers

Is anyone looking to the filter query builder? - I would love to collaborate on it, I have a starting point that work for the most basic things

  • TextField
    • equals
    • not equals
  • Number, Date
    • equals
    • not equals
    • greater than
    • greater than equals
    • less than
    • less that equals

But ideally I would love a second opinion, and maybe someone with more insights into PnPJS to be able to help out

@juliemturner
Copy link
Collaborator

juliemturner commented Nov 20, 2023

@Tanddant - Yes, @bcameron1231 got quite a ways on it but as a team there are some things that weren't exactly the way we'd want them to be, I think Beau could go into more detail, but it was around nested filters I believe

Here's his PR WIP: #2781

@bcameron1231
Copy link
Collaborator

bcameron1231 commented Nov 20, 2023

Hey @Tanddant definitely take a look at the PR Julie linked.

It's a bit crude at the moment and needs work, but it's my first exploration at possibly using Lamba type expressions instead. While Camljs is great, I personally prefer the look of a lambda expressions rather than consecutive chaining -- from a readability perspective.

Inside that branch, you'll see what I've done to handle scenarios like Number/Date versus Text field, specifically in the fomatValue() method within spqueryable. The reason I opted for an internal check/conversion on types is to make it easier for the consumer of the library... so they don't have to think about field types.

I'm very open to improving this, and certainly open to alternatives all together.

@m0jimo
Copy link

m0jimo commented Dec 8, 2023

Hi, I hope, its not completly off topic. I just come across limitation to query length. Query is limited to 160 characters.

  1. could be there an info about too long url? Happens usually with multiple filter conditions.
  2. automatically convert GET to POST with CAML format. I'm not sure it would be possible do that, but would be nice, right?

@juliemturner
Copy link
Collaborator

juliemturner commented Dec 8, 2023

@m0jimo - I think there is some confusion. The URL length is certainly a thing but it's a different thing than the overall length. So, one of the common ways to work around the URL length is to use alias parameters and we support that (https://pnp.github.io/pnpjs/sp/alias-parameters/). The second option if you go over the ~2000 character length (different for different browsers) is to use CAML queries because that would be in the post body, but we would not do that conversion for you. We do however support you doing it with the renderListDataAsStream or the getItemsByCAMLQuery methods.

@m0jimo
Copy link

m0jimo commented Dec 11, 2023

Thanks @juliemturner for provided links and ideas. I made a mistake in filter query which was not caused by its length. I'm aware of CAML support in PnpJs. I also found a parsers for OData filter, so I should be able to convert it to CAML myself in case it overcomes its length.

@kbeeveer46
Copy link

kbeeveer46 commented Jan 19, 2024

What about SharePoint alerts? We built our own custom document library UI web part using the files/folders PnP JS API but it doesn't have anything for alerts. We have a button on the page where they can manage alerts without having to use the backend SharePoint pages.

We had to create Azure functions which call the PnP PowerShell APIs to get/add/delete alerts. I wasn't sure if that's not possible to add to PnP JS or if it's just something that has never been added. It would be nice if we could get rid of all our Azure functions and be able to use PnP JS for that.

@juliemturner
Copy link
Collaborator

@kbeeveer46 - "Alerts" is a bit vague, I can think of 2 or 3 different things you might mean.

If you want to submit an enhancement request and give us details of what specific endpoints you're referencing we might be able to help but based on what you're describing it might be that the limitation is what you can do with delegated vs application level permissions. If the api endpoint was supported with delegated permissions then you wouldn't have to use an azure function... if you're using the azure function because that's how you're running PowerShell then if you can articulate what PowerShell commands you're referencing specifically I suspect you can do this already in the client side code, but maybe only with an extension method.

@kbeverforden
Copy link

@juliemturner When you're in a document library in SharePoint there's a set of buttons at the top like upload, delete etc. There's also a button that lets you set up alerts if anything has been added/changed/deleted from the library. I put a screen shot below.

Is there a way to manage (add/edit/delete) these using PnP JS? In PnP PowerShell they have the following cmdlets. I created Azure Functions that are called via http requests that run these cmdlets and return a response since I am not aware of another way to add/edit/delete alerts. We are using SharePoint online as a client portal so we don't want to make our clients use the "backend" pages of SharePoint like in my screen shot below. We wrote a custom document library web part that has an alert manager inside of it that does the same thing as the backend pages but with a better UI.

https://pnp.github.io/powershell/cmdlets/Get-PnPAlert.html
https://pnp.github.io/powershell/cmdlets/Add-PnPAlert.html
https://pnp.github.io/powershell/cmdlets/Remove-PnPAlert.html

image

@Tanddant
Copy link

@juliemturner What's the opinion on "undocumented APIs"?

I've been reverse engineering the news API, now not quite sure what to do with that 😅 - if it doesn't fit here I'll do an SPFx sample on it instead, the API isn't officially documented, so it might change and break, but it seemingly hasn't changed for a few years

@patrick-rodgers
Copy link
Member Author

@Tanddant well that's a good question. We have in the past reverse engineered APIs (pages forex) and used them in the library, but that isn't the best path forward as things can change/break unexpectedly. Depending on the API we can weigh the pros/cons. In my job-job I have to say, don't do that. But wearing my PnPjs hat I understand that sometimes folks need to solve issues we haven't fully supported in the service yet and generally encourage finding ways to solve the customer need.

@Tanddant
Copy link

@patrick-rodgers

Here's my current work: https://github.com/Tanddant/pnpjs/tree/v4-ODataFilterQuery

export interface IDepartment {
    Id: number;
    Manager: IDepartment;
    Alias: string;
    HasSharedMailbox: boolean;
    DepartmentNumber: number;
}

export interface IEmployee {
    Id: number;
    Age: number;
    Firstname: string;
    Lastname: string;
    Employed: boolean;
    Department: IDepartment;
    DepartmentId: number
    Manager: IEmployee;
    Created: Date;
    SecondaryDepartment: IDepartment[];
    SecondaryDepartmentId: number[];
}

const r = await sp.web.lists.getByTitle("Employees").items.filter<IEmployee>(
    Or(
        And(
            TextField("Firstname").Equals("Dan"),
            TextField("Lastname").Contains("Tof"),
            NumberField("Age").GreaterThan(25),
            BooleanField("Employed").IsTrue(),
            DateField("Created").IsBetween(new Date(2000, 1, 1), new Date(2024, 12, 31)),
            TextField("Firstname").Equals("Dan"),
        ),
        And(
            TextField("Firstname").In(["Beau", "Bob", "Dan"]),
            TextField("Lastname").Equals("Cameron"),
            NumberField("Age").LessThan(35),
            BooleanField("Employed").IsTrue(),
            LookupField<IEmployee, IDepartment>("Department").TextField("Alias").Equals("Intern Management"),
        ),
    )
)()

It works, but I can't start my code unless I comment out this stuff ^ - and then bring it back while running the code

@HughAJWood
Copy link

There are some slightly coupled parts to nodejs that don't work in React Native due to mobile only view. While I can see it is possible with behaviours to do this maybe, I've yet to come across a sample of using things like React Native Fetch instead. I know work on the React Native Components is underway so I think this would be a nice round solution for React Native components, especially as you can now build React Native Apps via cli for Windows as well.

@patrick-rodgers
Copy link
Member Author

There are some slightly coupled parts to nodejs that don't work in React Native due to mobile only view. While I can see it is possible with behaviours to do this maybe, I've yet to come across a sample of using things like React Native Fetch instead. I know work on the React Native Components is underway so I think this would be a nice round solution for React Native components, especially as you can now build React Native Apps via cli for Windows as well.

We'd certainly welcome a community sample, but it's hard to support making samples for all the possible SDK/lang/framework variants in the world. If it has its own fetch API and it matches the browser's/node-fetch than the behavior should be trivial. You can use our node fetch behavior as an example.

@HughAJWood
Copy link

HughAJWood commented Mar 28, 2024 via email

@patrick-rodgers
Copy link
Member Author

@HughAJWood - I am unfamiliar with react native. If there are things in pnpjs that block it from working, please do open an issue and describe them so we can review and see if/what changes we can make to accomodate. With v4 coming soon it would be a good time to review.

@HughAJWood
Copy link

HughAJWood commented Mar 28, 2024 via email

@patrick-rodgers
Copy link
Member Author

Thank you everyone for the great feedback and ideas for version 4. As we are getting close to launch I encourage everyone to try out the nightly builds for v4 and report any issues here in the list as normal. And of course please continue to share ideas on how we can continue to improve the library!

Thanks!

@patrick-rodgers patrick-rodgers unpinned this issue Apr 4, 2024
Copy link

github-actions bot commented Apr 7, 2024

This issue is locked for inactivity or age. If you have a related issue please open a new issue and reference this one. Closed issues are not tracked.

@github-actions github-actions bot locked and limited conversation to collaborators Apr 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

10 participants