add completionitemprovider and keep suggestions - intellisense

I created a completionitemprovider for my extension, but now the suggestions based on words in the document aren't shown. Do I have to provide each word in the document?
export class ScriptViewProvider implements vscode.CompletionItemProvider
...
extension.context.subscriptions.push(vscode.languages.registerCompletionItemProvider(
["language"],
this));
...
async provideCompletionItems(document : vscode.TextDocument, position : vscode.Position) : Promise<vscode.CompletionItem[]> {
let completions : vscode.CompletionItem[] = [];
let completion = new vscode.CompletionItem("bla", vscode.CompletionItemKind.Field);
completions.push(completion);
return completions;
}
It brings up "bla" when I type "b", but none of the other words in the document appear.

See this comment of an open VS Code issue.
When your CompletionProvider was registered using a DocumentSelector that is more significant than that of other providers and returns at least one completion item, the other providers are skipped.
The word-based suggestions provider is less significant and so it does not contribute any suggestions.
Depending on the nature of your extension you could try to define a less specific DocumentSelector when registering your CompletionProvider.
If this is not possible I think there is no other option than to providing all completion items yourself (including word-based suggestions).

Related

KeystoneJS `filter` vs `Item` list access control

I am trying to understand more in depth the difference between filter and item access control.
Basically I understand that Item access control is, sort of, higher order check and will run before the GraphQL filter.
My question is, if I am doing a filter on a specific field while updating, for instance a groupID or something like this, do I need to do the same check in Item Access Control?
This will cause an extra database query that will be part of the filter.
Any thoughts on that?
The TL;DR answer...
if I am doing a filter on a specific field [..] do I need to do the same check in Item Access Control?
No, you only need to apply the restriction in one place or the other.
Generally speaking, if you can describe the restriction using filter access control (ie. as a graphQL-style filter, with the args provided) then that's the best place to do it. But, if your access control needs to behave differently based on values in the current item or the specific changes being made, item access control may be required.
Background
Access control in Keystone can be a little hard to get your head around but it's actually very powerful and the design has good reasons behind it. Let me attempt to clarify:
Filter access control is applied by adding conditions to the queries run against the database.
Imagine a content system with lists for users and posts. Users can author a post but some posts are also editable by everyone. The Post list config might have something like this:
// ..
access: {
filter: {
update: () => ({ isEditable: { equals: true } }),
}
},
// ..
What that's effectively doing is adding a condition to all update queries run for this list. So if you update a post like this:
mutation {
updatePost(where: { id: "123"}, data: { title: "Best Pizza" }) {
id name
}
}
The SQL that runs might look like this:
update "Post"
set title = 'Best Pizza'
where id = 234 and "isEditable" = true;
Note the isEditable condition that's automatically added by the update filter. This is pretty powerful in some ways but also has its limits – filter access control functions can only return GraphQL-style filters which prevents them from operating on things like virtual fields, which can't be filtered on (as they don't exist in the database). They also can't apply different filters depending on the item's current values or the specific updates being performed.
Filter access control functions can access the current session, so can do things like this:
filter: {
// If the current user is an admin don't apply the usual filter for editability
update: (session) => {
return session.isAdmin ? {} : { isEditable: { equals: true } };
},
}
But you couldn't do something like this, referencing the current item data:
filter: {
// ⚠️ this is broken; filter access control functions don't receive the current item ⚠️
// The current user can update any post they authored, regardless of the isEditable flag
update: (session, item) => {
return item.author === session.itemId ? {} : { isEditable: { equals: true } };
},
}
The benefit of filter access control is it doesn't force Keystone to read an item before an operation occurs; the filter is effectively added to the operation itself. This can makes them more efficient for the DB but does limit them somewhat. Note that things like hooks may also cause an item to be read before an operation is performed so this performance difference isn't always evident.
Item access control is applied in the application layer, by evaluating the JS function supplied against the existing item and/or the new data supplied.
This makes them a lot more powerful in some respects. You can, for example, implement the previous use case, where authors are allowed to update their own posts, like this:
item: {
// The current user can update any post they authored, regardless of the isEditable flag
update: (session, item) => {
return item.author === session.itemId || item.isEditable;
},
}
Or add further restrictions based on the specific updates being made, by referencing the inputData argument.
So item access control is arguably more powerful but they can have significant performance implications – not so much for mutations which are likely to be performed in small quantities, but definitely for read operations. In fact, Keystone won't let you define item access control for read operations. If you stop and think about this, you might see why – doing so would require reading all items in the list out of the DB and running the access control function against each one, every time a list was read. As such, the items accessible can only be restricted using filter access control.
Tip: If you think you need item access control for reads, consider putting the relevant business logic in a resolveInput hook that flattens stores the relevant values as fields, then referencing those fields using filter access control.
Hope that helps

Actual property name on REQUIRED_CHILDREN connetion

In relay, when using REQUIRED_CHILDREN like so:
return [{
type: 'REQUIRED_CHILDREN',
children: [
Relay.QL`
fragment on Payload {
myConnection (first: 50) {
edges {
node {
${fragment}
}
}
}
}
`
]
}]
and reading off the response through the onSuccess callback:
Relay.Store.commitUpdate(
new AboveMutation({ }), { onFailure, onSuccess }
)
the response turns the property myConnection into a hashed name (i.e. __myConnection652K), which presumably is used to prevent connection/list conflicts inside the relay store.
However, since this is a REQUIRED_CHILDREN and I'm manually reading myConnection, it just prevents access to it.
Is there an way to get the actual property names when using the onSuccess callback?
Just as Ahmad wrote: using REQUIRED_CHILDREN means you're not going to store the results. The consequence of it is that data supplied to the callback is in raw shape (nearly as it came from server) and data masking does not applies.
Despite not storing the data, it seems to be no reason (though core team member's opinion would be certainly more appropriate here) not to convert it to client style shape. This is the newest type of mutation, so there is a chance such feature was accidentally omitted. This is normal that queries are transformed to the server style shape, the opposite transformation could take place as well. However until now is has not been needed - while saving the data to the store and updating components props, transformation was made meanwhile. Currently most of Relay team is highly focused on rewriting much of the implementation, so I would not expect this issue to be improved very soon.
So again, solution proposed by Ahmed to convert type to GraphQLList seems to be the easiest and most reliable. If for any reason you want to stand by connection, there is an option to take GraphQL fragment supplied as children (actually its parsed form stored in __cachedFragment__ attribute of that original fragment) and traverse it to obtain the serializationKey for desired field (eg __myConnection652K).

Prestashop Module: hooks and orders

I am having multiple questions about this topic
As the title states, I am in need to find the correct hook to bind when an order has been placed and the payment was accepted.
1.) Which hook should I bind in my module when an order has been placed (and payed)?
2.) I am under the impression that there is no generalized hook for this, since some payment methods set the order status to 'payed' automatically (like a successful PayPal transaction) while other methodes require the shopowner to manually set the status to 'payed'. Are there any more than just those two that must be called to cover most cases?
3.) Eventhough I am still hoping that there is a generalized hook, if there's none, how would I approach this issue? Bind "actionPaymentConfirmation" aswell as "displayPaymentReturn" to cover both cases?
4.) Why is the hook "actionPaymentConfirmation" never called when I set the order status to "payed" in the backoffice. My code looks like this
public function install() {
if (!parent::install() || !$this->registerHook("actionPaymentConfirmation")) {
return false;
}
return true;
}
public function actionPaymentConfirmation($params) {
print_r($params); // stepping through with XDebug but the function is never being invoked
}
5.) Does anyone know a free module doing something simmilar I can dig into to get a better idea?
6.) Or might it be easier to override Prestashops core classes to tackle my problems? To break it down, I want to execute stuff after an order has been placed and the status is set to payment was accepted or remotely accepted.
Well, I hope I am not asking to much stuff at the same time, but as you can see, I am interested in mastering these things but have some troubles along the way. Have now been trying and especially search for answers for days now without any luck.
Regards!
I assume that you're with PrestaShop 1.5
1 actionValidateOrder (for new order) & actionOrderStatusPostUpdate (here you can check about the "paid" status)
2 Like 1.
3 Like 1.
4 The hook is actionOrderStatusPostUpdate
5
public function install()
{
return (parent::install()
AND $this->registerHook('newOrder')
AND $this->registerHook('actionOrderStatusPostUpdate'));
}
public function hookNewOrder($params)
{
return $this->hookActionOrderStatusPostUpdate($params);
}
public function hookActionOrderStatusPostUpdate($params)
{
//$params['newOrderStatus'] // after status changed
//$params['orderStatus'] // after order is placed
}
6 Look at 5.
Note: actionValidateOrder the new name (alias) of newOrder

Check if property exists in RavenDB

I want to add property to existing document (using clues form http://ravendb.net/docs/client-api/partial-document-updates). But before adding want to check if that property already exists in my database.
Is any "special,proper ravendB way" to achieve that?
Or just load document and check if this property is null or not?
You can do this using a set based database update. You carry it out using JavaScript, which fortunately is similar enough to C# to make it a pretty painless process for anybody. Here's an example of an update I just ran.
Note: You have to be very careful doing this because errors in your script may have undesired results. For example, in my code CustomId contains something like '1234-1'. In my first iteration of writing the script, I had:
product.Order = parseInt(product.CustomId.split('-'));
Notice I forgot the indexer after split. The result? An error, right? Nope. Order had the value of 12341! It is supposed to be 1. So be careful and be sure to test it thoroughly.
Example:
Job has a Products property (a collection) and I'm adding the new Order property to existing Products.
ravenSession.Advanced.DocumentStore.DatabaseCommands.UpdateByIndex(
"Raven/DocumentsByEntityName",
new IndexQuery { Query = "Tag:Jobs" },
new ScriptedPatchRequest { Script =
#"
this.Products.Map(function(product) {
if(product.Order == undefined)
{
product.Order = parseInt(product.CustomId.split('-')[1]);
}
return product;
});"
}
);
I referenced these pages to build it:
set based ops
partial document updates (in particular the Map section)

Problem with RavenDB 'Hello World' tutorial

I am going through the RavenDB tutorial on the RavenDb.net website.
It was going fine until I got to the code block for creating an index.
This code segment is direct from RavenDB.Net website.
store.DatabaseCommands.PutIndex("OrdersContainingProduct", new IndexDefinition<Order>
{
Map = orders => from order in orders
from line in order.OrderLines
select new { line.ProductId }
});
I get an error on compile: "The non-generic type 'Raven.Database.Indexing.IndexDefinition' cannot be used with type arguments."
If IndexDefinition is non-generic, why is it used as generic in the sample code? Where is the disconnect?
Thank you for your time
Jim
Depending on your using statements you may be referencing the wrong IndexDefinition class (from another Raven assembly). Try adding this to the beginning of your file:
using Raven.Client.Indexes;
You might need to remove other using statements as well. I guess this is one reason why Microsoft recommends using unique names for classes even in the presence of namespaces.