Replace preact with solidjs

I decided to replace preact with solidjs to save memory. The codebase remains mostly the same, but the package size has decreased by 25.89 kB!. From 53.41 kB to 27.52 kB.

These PRs look great to merge.   :)


Bump deps: freetype, glib, png, rsvg, webp, zlib-ng

Marked as draft to investigate CI failures on macOS.

Dankjewel Kleis!


Json::assertHas doesn't work as expected

Hi,
I just updated the library in my project to latest version (1.2) and replaced some places to use KernelBrowser::browser()->json()->assertHas('selector'). But it seems that it doesn't work as expected.
I'm testing a json api endpoint which returns this json:
{
  "limit": 50,
  "total": 1,
  "page": 1,
  "pages", 1,
  "_links": {
    "first": {
      "href": "/api/backend/chains?_page=1&_per_page=50"
    },
    "last": {
      "href": "/api/backend/chains?_page=1&_per_page=50"
    }
  }
  "_embedded": {
    "items": [
         {"id": 1, "label": "Grand compte par défaut"}
    ]
  }
}

Here is my test which fails:
$this->browser()->get('/uri')->assertStatus(Response::RESPONSE_OK)
    ->json()->assertHas('total');

Here is my test which succeeds:
$response = $this->browser()->get('/uri')->assertStatus(Response::RESPONSE_OK)
    ->json()->decoded();
self::assertSame(1, $response['total']);

I tried to replace the Assert::try in Json::assertHas by Assert::that($selector)->isNotEmpty() and it works.
I think the problem comes from length used which in this case returns something empty as 1 is not countable...
I don't know if my solution is the best to use. If so, let me know I can provide the PR. :-)
Thank you

hello @flohw
indeed our tests are missing a case where the value is an int, see https://github.com/zenstruck/browser/blob/1.x/tests/JsonTest.php#L68
You mean Assert::that($this->search($selector))->notEmpty(), right?
because if you do Assert::that($selector)->isNotEmpty() it will just test the string $selector (in your case total).
I don't remember why we used length() here. I remember that we couldn't return true here on null values, but it is by design in JMESPath spec :disappointed:
Then I'd say the solution would be to use isNotNull() because we want empty string values to return true here.
We should also change assertMissing() as well

Sorry, I only have isNotEmpty() with my auto completion on Assert::that
zenstruck/browser 1.2.0
zenstruck/assert 1.2.0
My changes in Zenstruck\Browser\Json: (original code commented)
    /**
     * @param string $selector JMESPath selector
     */
    public function assertHas(string $selector): self
    {
        Assert::that($selector)->isNotEmpty();
//        Assert::try(
//            fn() => $this->search("length({$selector})"),
//            'Element with selector "{selector}" not found.',
//            ['selector' => $selector]
//        );

        return $this;
    }

I will try, I am fighting with uninitialized entities properties, not sure if it's due to doctrine or foundry for now and don't understand why...

Out of context but we never know, it may be related to zenstruck/foundry :slightly_smiling_face:
Just quickly, I am still investigating
```php
$entity = $this->fixtures->getReference('reference'); // Get entity from doctrine fixtures bundle created with foundry (entity not foundry proxy)
$this->browser()->delete("/api/{$entity->getLinkedEntity()->getOtherEntity()->getId()}"); // here is the problem with uninitialized entity::$linkedEntity which I didn't had before.
// This works
$entity = $this->fixtures->getReference('reference');
$id = $entity->getLinkedEntity()->getOtherEntity()->getId();
$this->browser()->delete("/api/{$id}"); // Succeeds

We are upgrading to php 8.2 from 8.1, all packages are up to date.
Hard to debug because of doctrine generated proxies which I don't know very well...

It's only if you faced the problem recently, if not, just ignore this section :wink:
</details>

Assert::that($selector)->isNotEmpty();

this code won't work, you're testing the string $selector. $json->assertHas('not existing selector') will not fail since the string is not empty
BTW, zenstruck/assert 1.2.0 is the last version, son isNotNull() exists: https://github.com/zenstruck/assert/blob/v1.2.0/src/Assert/Expectation.php#L83

sorry, I don't understand your Foundry problem. both versions seems similar to me

Ho I missed the $this->search call...
So both works: isNotEmpty and isNotNull and I do agree that isNotNull should be used.
I will provide a PR. How would be assertMissing be changed?
No problem for the other issue, it looks the same to me too but don't behave the same. ^^ Thanks.

Found with isNull.
I added tests on these values:
yield ['{"foo": 1}', 'foo'];
yield ['{"foo": ""}', 'foo'];
yield ['{"foo": 0}', 'foo'];
yield ['{"foo": null}', 'foo'];
yield ['{"foo": false}', 'foo'];

The only remaining problem is for {"foo": null} as null could be return because of search or because search didn't found the selector... Any idea how to resolve this edge case?

The only remaining problem is for {"foo": null} as null could be return because of search or because search didn't found the selector... Any idea how to resolve this edge case?

I think for these assertions we have to assert it has the a value (using Json::assertHas()).

yield ['{"foo": 1}', 'foo'];

This isn't an empty-ish value.

assertHas has the same issue as the value is null it's considered missing.
And assertMissing don't find the value as it's null and the exception is not thrown.
Yes I added this test because of my initial problem : length was not working on int.

I doubt we will be able to distinguish "null value" and "node not present" with JMESPath
see this comment: I kinda agree when he/she says:

the specification is broken by design

So I remove the test and provide the PR. :slightly_smiling_face:

Yeah... I'm not seeing a great solution here. @nikophil is right, it isn't part of the spec but lots of discussion around this.
It is possible using the keys and contains function but not sure we can do this in a generic way (by just accepting a foo.bar.baz $selector). Maybe I'm wrong?

https://stackoverflow.com/a/51519959 is what I'm referring to.

I tried to do some things base on some explode which didn't work and produce an ugly code. ^^
I am not sure how it could be done differently or how to combine the different Assert possibilities.
And my other bug which may require me to update all my tests is painful.
Leave my pr open, I'll try to search a bit more on monday. If you find a solution during the weekend you can close my pr and create your own or provide the diff and I will be able to apply in my branch. I am already happy to be able to help a bit here anyway. :slightly_smiling_face:
Thank you.

I don't see other way around than using explode.
Or maybe a regex will do the job, not sure it's less ugly :upside_down_face:
https://regex101.com/r/DOqsmk/1
https://3v4l.org/Yeg0m
I'm also wondering what would be the syntax if the node is a root node. ie: {"total": null}

explode will be fine and easier to read. :sweat_smile:
I saw @ somewhere but didn't tried and not sure how to use it. Maybe contains(keys(@), 'total') :thinking:

yes it works!
you got a playground for jmespath here: https://jmespath.org/

@kbond do you see some edge cases? I don't know if there if we can pass to assertHas() and assertMissing() another kind of selector than "regular" ones like that foo[0].bar.baz

That's what I've been thinking too - should we only support ./[x] notation here?
If so, we should have tests for:

foo
foo.bar
foo.bar.baz
[0]
foo[0].bar
foo[0][1]
missing anything?

I soooo want this: https://github.com/symfony/symfony/issues/48067

Hello there,
With one day late, I am working a bit on this.
I managed to make it work for all of your cases @kbond except for [0] and foo[0][1] because keys function expect to have an object and in both cases it's an array.
The test cases are yield ['[null]', '[0]']; and yield ['{"foo": [[1, null]]}', 'foo[0][1]'];. All the added tests are on a null value.
The method look like this:
public function assertMissing(string $selector): self
{
    $prefix = 1 === preg_match('#^\[#', $selector) ? ''<EMAIL_ADDRESS>    $exploded = explode('.', $prefix.$selector);
    $key = array_pop($exploded);
    $keySelector = implode('.', $exploded);

    Assert::that($this->search("contains(keys($keySelector), '$key')"))
        ->equals(false, 'Element with selector "{selector}" exists but it should not.', ['selector' => $selector]);

    return $this;
}

I am not sure about adding the @. but this is the only way I found to prevent multiple ifs statements.
Also the $prefix which is empty or<EMAIL_ADDRESS>is required because selector like this one: yield ['[{"foo":"bar"}]', '[0].foo']; doesn't work with @.[0] nor @[0] but does with [0].
Only two edge cases remain: [0] and foo[1][0] which may not be logical in this context or at least have workarounds:

->assertThat('length(@)', 0) and ->assertThat('length(foo[0][1])', 0)
->assertThat("!contains([0], 'needle')") and ->assertThat("!contains(foo[0][1], 'needle')").

Given the names has and missing maybe it's ok as for arrays we usually see contains which will require a second argument on both of the existing methods doesn't provide: the needle.
What do you think? Any advice about the last bit ([0] and foo[0][1])?
Note: The method assertHas with exactly the same code (except that equals tests on true) works as well as this one.

Unrelated doctrine bug
The unrelated bug I had was fixed and released in doctrine/orm because of the issue 10336, Kevin :slightly_smiling_face: (no link because no need to cross reference the issue)
It was related to clearing the EM...

Hi @flohw
would you push the code on your PR please? we could explicitly see the failing cases
thanks!

Hi, I just pushed the changes.


feat(gui): Add full filename to file selector

This adds the display of the full filename to the file selector.

Change-Type: minor

In the bottom example, where the filename is still "too long", does mouse-hovering over the filename at the bottom show the full filename as a tooltip?


[WIP] Add toxicity example

This PR adds a cool example about toxicity model
This is a WIP PR

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint.


Campaign-Defined Plot Gallery

A very useful tool would be to have a campaign-defined plot gallery available on the MSS server URL.
That means a set of pre-defined (top view) plots that are important for the specific measurement campaign.
It could be built upon the "plot gallery" structure.
Pre-definition of the plots should include map projection section, list of parameters (also allow multilayer plots),
a list of  levels. The exact plot settings would be defined in a config file, like in retriever.py that uses "automated_plotting" in mss_settings.json
An exact website layout needs to be defined/discussed:
There could be a page displaying all plots in a gallery and one for single plots.
Maybe also different galleries for different scientific themes (e.g. chemistry, clouds, gravitiy waves)
There could be a choice box to set the initialisation time and valid time.
There could be a clickable arrow to move in valid time and initialisation time.

this sounds a bit like on demand plotting by using some AJAX components.
This gets in a direction of adding an alternative to our QT UI by an interactive web interface.

In principle, one could also have a UI-like web interface. I am not sure, whether we would need that, since the installation of the UI works very well. The idea behind this issue is somewhat different. I think, the value of such a gallery of pre-defined plots is to get a scientific overview without the need of clicking always the same buttons on the UI.
So for a complete interactive access, I don't see why we must double the functunality of the UI

In practice the plots should be pre-generated on a manual trigger (cronjob) for performance.
That is similar to the current state.
What would be missing is a control to switch between different times. init/valid. Maybe only valid for starters?
Beyond that one can think about several different UI features replicating, e.g. Andreas Dörnbracks website.
I think we are in a good position here to have in addition to the WMS server a website browsable without the MSUI.
Such a website would compliment the MSUI tool very well (for getting an overview compared to specific flight planning).


Added build_version optional parameter to CLI release command

Why: we need to support distribution of WinForms/WPF apps from .msi and .zip files
What/How:

added --build-version extra parameter to distribute release command
updated swagger (only build_version change and not the whole description from bifrost)
generated autorest models
passed the buildVersion to release_uploads endpoint call

Why it draft and next steps

We need to merge changes in releases service
Know when we ready to release new cli

 Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.:x: snowpardx sign nowYou have signed the CLA already but the status is still pending? Let us recheck it.


Add option to treat temporal warnings as errors in eoexecutions

Do you think this might be useful?

Codecov Report
All modified lines are covered by tests :white_check_mark:

Comparison is base (4b185cb) 92.41% compared to head (4b185cb) 92.41%.

:exclamation: Current head 4b185cb differs from pull request most recent head b58e047. Consider uploading reports for the commit b58e047 to get more accurate results

:exclamation: Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@           Coverage Diff            @@
##           develop     #760   +/-   ##
========================================
  Coverage    92.41%   92.41%
========================================
  Files           41       41
  Lines         4300     4300
========================================
  Hits          3974     3974
  Misses         326      326

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

BTW, perhaps we should be adding to the changelog as we go along, not before each release.

I was thinking about it, but enforcing it seems like a drag compared to 5mins of staring at the history to come up with a condensed history.
I am willing to go with raise_on_temporal_dimension_mismatch though it is long

raise_on_temporal_dimension_mismatch

Do you feel that the dimension keyword is necessary? IMO it's clear enough to me, so I would drop it, but if you don't want to drop it, then I'm OK with the current name as well.

raise_on_temporal_dimension_mismatch

Do you feel that the dimension keyword is necessary? IMO it's clear enough to me, so I would drop it, but if you don't want to drop it, then I'm OK with the current name as well.

I am inclined to keep it because a temporal missmatch is also if the timestamps don't match, but we only check dimensions. But then again the docs do clarify it further :thinking:  so maybe we can drop it


Reduce the number of isCmd calls slightly in the XRef class

This reduces the total number of function calls, when reading the XRef table respectively when fetching uncompressed XRef entries.
Note in particular the XRef.readXRefTable method, where there're two back-to-back isCmd checks rather than just one.

/botio test

Looks good; thanks!


Feature request: Number#fround(precision)

In analogy to Number#round().

While Number#round allows you to control the precision, this doesn't seem to require that, so it could just be mapped as an alias similar to pow, abs, etc. Would this satisfy your needs?

The idea is for Number#fround to do allow to control precision, in the same way as Number#round does.
Note that neither Math.round nor Math.fround themselves have a precision parameter built-in.
I'm currently shimming it like so, btw: https://github.com/Slayer95/Pandora-Showdown/blob/8fe91896fdd4a4927fbde6ffdc098945254ca651/tools.js#L47-L65

So, after playing around with your example a bit, I'm still having trouble understanding the meaning (or at least the utility) of having a "places" argument. round is clear as this is natural language. Although according to the spec it rounds to the nearest integer, it is not a stretch for a parameter to allow rounding to a specific place. fround, however is not natural language, the method specifically rounds to single-precision, and the places argument isn't immediately clear what it's indicating.
Anyway, let's set all this feedback aside. In either case, this idea is a perfect candidate for using the new plugin system of v2.0. I just recently created a boilerplate repo here. There are a lot of notes and it should be easy to follow along.

Going to close this for now. Let me know if there are issues with the plugin mechanism, etc.


Add validators for CRDs

PR #54 adds in support for CRDs, but does not add in the validators into the CRD schemas. We'll likely want to take advantage of this functionality, so this issue will track adding that support.

@sbezverk Thanks for volunteering to take this one on! Here is what I think you want to validate:

https://github.com/ligato/networkservicemesh/blob/master/pkg/apis/networkservicemesh.io/v1/types.go#L38
https://github.com/ligato/networkservicemesh/blob/master/pkg/apis/networkservicemesh.io/v1/types.go#L64
https://github.com/ligato/networkservicemesh/blob/master/pkg/apis/networkservicemesh.io/v1/types.go#L90

@mestery I would like to confirm which level of validation you have envisioned, would you like to validate just the format of below fields(length/content) or some logic (both name and uuid must be present) etc.
if it is former then by just extending CRD definition with validation by openAPIV3Schema  it can be achieved, latter would require web-hooks.
message NetworkServiceEndpoint {
    string name = 1;
    string uuid = 2;
};

message NetworkService {
    string name = 1;
    string uuid = 2;
    string selector = 3;

    message NetmeshChannel {
        string name = 1;
        string payload = 2;
    };
    repeated NetmeshChannel channels = 4;
};

Appreciate your comments.

I was envisioning the former. Thanks!

@mestery
type NetworkService struct {
	Name     string                           `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
	Uuid     string                           `protobuf:"bytes,2,opt,name=uuid" json:"uuid,omitempty"`
	Selector string                           `protobuf:"bytes,3,opt,name=selector" json:"selector,omitempty"`
	Channels []*NetworkService_NetmeshChannel `protobuf:"bytes,4,rep,name=channels" json:"channels,omitempty"`
}

It looks like none of the elements of NetworkService are required, is it by design? if it is, appreciate a comment why.
Also I could not find if you have any limitations which needs to be enforced. Should I use k8s common limits for names and uuid?


feat(SolScript): CW-7488 Staking withdraw script

Task linked: CW-7488 Add withdraw support to coin-sol


Radium inserts img elements for background gradients

Hi!
I just noticed that if you use CSS gradients, Radium will insert img elements into the HTML. This freaks out my server-side router who tries to route the URL's. Is there anything that can be done about this?
It looks like this:

I have two gradient rules:
wrapper: {
    background: 'linear-gradient(-45deg, transparent 3.5em, ' + colors.whitegrey + ' 3.5em)',
    padding: `1.3em 7em 1.3em ${constants.sidePadding}`
}

and:
box: {
    background: colors.whitegrey + ' repeating-linear-gradient(-45deg, transparent, transparent 3px, rgba(0,0,0,0.05) 1px,rgba(0,0,0,0.05) 6px)'
}

At first I tried multiline template strings but switched to normal strings as I thought that was the issue. As you can see, I still have template strings in there.

Sorry, false alarm. It must be the style-loader, since I moved the gradients to a CSS file and it still happens. Closing this.


[BUG] Character image doesn't render

Scope
When an image url is provided to the the gallery manager on the character sheet, the image doesn't render.
To Reproduce
Steps to reproduce the behaviour:

Create a new NPC
Click "Gallery" then "Add Online Image"
Provide https://static.wikia.nocookie.net/criticalrole/images/c/c5/Avantika_-_Rammaru.jpg/revision/latest?cb=20200523182510 as the image.
Exit the gallery manager back to the character sheet.

Expected behaviour
The image should render inside the RpgManager block. Instead, only a grey image appears.
Screenshots

Additional context
It looks like Rpg Manager is normalizing the image url such that all letters are lowercase. Correcting the url manually in the RpgManagerData block resulted in the expected behavior.

Hi @cstby
One of the thing I noticed is that some providers block you downloading the same image multiple times. This means that after a while, Obsidian cannot get the image any longer.
If I open the image you linked in the description, I see the grey image, not the correct one.
Also, if I were you, I would link the file, removing everything else behind it:
https://static.wikia.nocookie.net/criticalrole/images/c/c5/Avantika_-_Rammaru.jpg
Using the image link directly, is it working?


Base functionality is wrong? Or am I being stupid?

Hey guys,
I'm trying to add some versioning to my ASP.NET Core project and running into a very basic issue.
Thinking about my requirements for versioning, the very first thing on my list is:

Upon defining a new version, say v1.1, the full functionality of v1.0 should already be available, at which point I can then decide which methods to remove, replace etc.

Looking at the documentation for this, the samples propose a new controller for each version. This leads me to believe I am expected to re-implement the full API surface for each revision! Call me crazy, but that just isn't practical (unless you have a tiny API).
I have tried creating new controllers by inheriting the older version, but this does not work properly when replacing a method with a newer version. The ambiguity resolution does not favour the most derived method, thus fails when it finds two methods that implement the same action. Overriding is only possible if the parameters match exactly which of course is rarely the case. I have no choice but to reimplement every method on every controller.
Another option is the [MapToVersion] attribute, but again the default behaviour of this is causing me issues. If I use [MapToVersion("2.0")] and then later introduce a v2.1 version, the method reverts to its pre-2.0 behaviour because it uses an == instead of a >=. This then requires a manual search for all methods using [MapToVersion] and to tag them with the new version too. Ultimately, this manual process will lead to methods being forgotten and bugs being introduced.
Is there any advice on how to inherit existing functionality into each new version? I'm struggling a bit.
Many thanks,
Ross.

A controller per API version is certainly the safest and easiest to understand, but it's not a hard requirement. As you've noted, you can use action interleaving to have a single controller with multiple versions when there are small variations between API versions. You can also use a combination of both. There is currently an open issue to address the feature request to support interleaving across controllers. This would make implementation large API surfaces easier. Unfortunately, it's a lot more complicated under the hood that it looks. That will likely be some time coming.
If I step on my services soapbox, every service author's goal should be to make their clients' lives easier - and stable. All too quickly service authors want to jump to making their implementations easier for them. Certainly that's not unfounded and this project aims to help make that a reality, but not at the cost of unpredictably for clients. It's, therefore, important that versions match exactly by default. This makes things predicable for the service and clients. All too often, service authors only consider new API versions. Well, what about old API versions that are removed? This eventually does happen and can even happen in the middle of a range (ex: a bad version becomes unpublished). This becomes a mess when ranges are used. I've witnessed teams doing this in the field and it didn't end well.
All that being said, there is a way to support a range of sorts, but it's not provided out-of-the-box. There are many extension and customization points. I can't remember if there are an examples in the wiki, but there are definitely examples in the issues. You can create an attribute or use conventions that produces a range albeit a discrete range. It might look like:
[ApiVersionRange(1, 2, MinorStep = 1)]
public class MyController : Controller
{
   [MapToApiVersionRange(1.5, 2, MinorStep = 1)]
   public IActionResult Get() => Ok();
}

One of the many reasons why this isn't supported out-of-the-box, is that an API version doesn't intrinsically support incrementing or decrementing. That process is wholly dependent on your style of versioning. Nevertheless, there are plenty of base implementations to start from or you can roll your own IApiVersionProvider. The framework doesn't care about attributes, it only cares about this interface. That means you can create your own attributes from scratch if you want to.
You might also consider using conventions. The process of creating complex mapping will be a little onus, but you'll have full control over how to graft the API versions onto controllers and their actions. You might even achieve this using your own configuration (ex: a *.json file, *.xml file, db, etc) to populate at startup and then apply the conventions.
Ultimately, the least amount of mapping comes from using independent controllers. All actions implicitly map to the same API version as their defining controller. One of the many ways to make this less painful is to keep all of the business logic out of the controller. The controller is the service. The only thing it should be doing is invoking business logic and controlling the wire protocol. If you adhere to that type of style, then it should be pretty safe to copy and paste new controllers for new API versions and only modify the minimal changes. Most service taxonomies have a stated versioning policy of N-2 or something like that. If the number of API versions you support per service is less than 5 (just throwing out a number), it shouldn't be that hard to manage.
Beware trying to make the API version of all services congruent. I won't say don't do it, because it can make it easier for clients, but each service should be allowed to evolve independently. If you're trying to achieve having all your services support the same API version, then you'll definitely want to use a custom attribute or conventions because it will be much easier to manage.
I hope that helps. Let me know if you have more questions.

Thanks for the detailed reply, much appreciated!
I'll have to mull over some of your points on version ranges. You definitely have an angle on this that's different to my own. Perhaps this is a comparative lack of experience on my side.
Judging by the opening sentence to your second paragraph, I fear I gave a bad impression of my motivations! To be clear, my concern is exactly that of making my clients' lives "easier and stable". It looks like we've arrived at a different conclusion on how best to achieve that!
To aid understanding, let me put a bit more context on this. I am doing this for backwards compatibility. Once v1.0 of the API is released it must remain unchanged because there is a mobile application that depends upon it (and I do not want to force our users into an upgrade). On the flip side, the product is young and we will inevitably want to introduce breaking changes, possibly even revisions of the API structure as we evolve our thinking on how the service should work. I foresee there being a v1.1, v1.2 etc. over the course of the first year. Ultimately, the intention is to make the API publicly available.
You talk of each controller being an independent service, so I suspect you have bigger APIs to manage than me. In our case, there is one logical "service" and the controllers each implement a particular aspect of that service (i.e. the individual REST resources). It is therefore easier for clients if I version the API as a whole. I do not want new consumers hunting around in documents to figure out which particular version they need to call for each API. Simply point at the latest version and go.
The rest of my thinking stems from safety.
I am completely on board with introducing a new controller per version.
[IntroducedInVersion("1.0")]
[Route("{api-version}/users")]
public class UsersController1_0 : Controller
{
  // all methods of 1.0
}

I think we disagree on how to introduce later versions. In my experience, copy and pasting duplicate code is not a good approach. Your point on the controllers being no more than thunks to another class is noted, but I feel like this may be a hack to cover the fact that the route didn't land in the correct place to start with.
In my opinion, the safest way to introduce a new version is simply to decree "v1.1 now exists" at a higher level of abstraction and then to describe the changes present in that version. The functionality in the preceding version should be available by default. In theory, there is less code to maintain and less chance of introducing mistakes through manual housekeeping.
[IntroducedInVersion("1.1")]
[Route("{api-version}/users")]
public class UsersController1_1 : Controller
{
  // MODIFIED FUNCTIONALITY ONLY
}

This was actually incredibly simple to implement using just a custom attribute and a custom convention. A testament to how well designed MVC is 👍. I use another attribute [RemovedInVersion] to flag the methods that are being replaced in a later version (or no longer available).
I will be sure to report back if my experience from running this approach changes my viewpoint!

Apologies if I got a little riled up.
In my vernacular, resource == API. IMO, there is no such thing as a Web API per se. The API is HTTP (e.g. the uniform interface). Arguably, that's why purists, including Fielding himself, disagree with the concept of API versioning and tend to accept media type negotiation as the only practical method of versioning. I can get onboard with that position.
You can certainly slice implementations, even for a single resource, across multiple controller types. This would certainly make sense from something like DELETE, which is unlikely to ever be different for any API version.
There are many, many ways to version resources and I don't think there is one single implementation flavor that matches them all. Part of that decision will be based on the number of resources and the cohesion between them. In large service taxonomies, services tend to use a date rather than a number (which is supported) because a number becomes meaningless at some point. While it's admirable to have a single version for all resources, that is unmanageable in large service taxonomies and can be argued to be counter to service-orientation. However, for small sets of resource or a particular resource group there's no reason why they can't all have the same version.
It sounds like what you want is actually inheritance. This can work if you use an add or update only approach. You cannot remove an inherited method/action, so to completely sunset an action, things get tricky. In ASP.NET Core, you don't need to do anything special to make picking up existing actions work.
For example:
namespace App.Controllers.V1
{
  [ApiVersion("1.0")]
  [Route("api/[controller]")]
  public class UsersController : Controller
  {
    [HttpGet]
    public virtual IActionResult Get() => Ok(new []{ new User() });
  }
}

namespace App.Controllers.V2
{
  [ApiVersion("2.0")]
  [Route("api/[controller]")]
  public class UsersController : V1.UsersController
  {
    [HttpGet("{id}",Name="GetUserByIdV2")]
    public virtual IActionResult Get(int id) => Ok(new User(){ Id = id });

    [HttpPost]
    public virtual IActionResult Post(User user) =>
      CreatedAtRoute("GetUserByIdV2", new {id = 42}, user);
  }
}

namespace App.Controllers.V3
{
  [ApiVersion("3.0")]
  [Route("api/[controller]")]
  public class UsersController : V2.UsersController
  {
    [HttpDelete("{id}")]
    public virtual IActionResult Delete(int id) => NoContent();
  }
}

You don't have to separate version by namespace. It's only one of many possible forms of organizing the implementation.
I'm not sure where you are in your transition, but here's some additional things to be consider about versioning via the URL:

You can't have a default route without declaring multiple routes on at least one controller

This may not be an issue for you, but it is for some
If your existing routes don't have a version segment, then you'll want this for the initial version

Hypermedia links generated for HATEOS requires coupling because a service must know the applicable version of a related resource to put in the URL

Resources usually evolve independently and it's up to a client to decide which version to request
Since you're using a single version for all resources, this may be a non-issue

There are more minor points, but those are a few that can cause quite a bit of grief. The URL segment approach is common, but fundamentally approaches the problem incorrectly within the context of REST IMO. A resource is a resource. The API version is really just a different representation of a resource. This is the strongest argument to version by media type. The URL is the identifier of a resource in accordance with the uniform interface constraint. An identifier for the same resource should not change between versions. For example, the URLs api/v1/users/1 and api/v2/users/1 implies that the resources are different, when, in fact, they are not. In your case, they are possibly different representations, but in each case, the resource is for a User with ID 1. Media type negotiation is not so convenient to consume, so the query string approach tends to be a reasonable compromise. This allows for api/users/1?api-version=1.0 and api/users/1?api-version=2.0.  If you need or want to support the implicit api/users/1 route, that's possible too. The query string is never considered in routing (on any stack I know). This gives clients more stable and consistent URLs. Appending the API version to the URL tends to be simpler for clients too.
Ultimately, the decision is up to you. My musings and opinions shouldn't be weighted any heavier than others. While I have done a lot of research and made a lot of observations from the field, there is no perfect answer. The goal of this project was to support the most common versioning methods and let service authors decide what works for them. Some care more about conforming to the REST constraints than others.
Naturally, you're free to go your own route as well. Inheritance in its many forms is something that the community is asking for so it's something I am actively looking into. May you find this all informative and help you in rolling out your service[s].

I definitely fall into that camp of people that care less about conforming to REST than others. My background is in commercial development so I am far more practically focused than academic.
Fielding's HATEOAS is an interesting concept, but putting my practical hat on for a minute I am unable to see how it fits the modern mobile app/service API approach. The idea that a client could recognize the semantics of an operation and render an appropriate UI simply by the presence of a new hyperlink in the response is somewhat fanciful to me. Modern mobile applications tend to be highly refined, with bespoke purpose-specific gestures for different operations. New operations need to be properly considered and designed-in. Hyperlinks work on the web, because it's used by humans! I have actually used APIs with HATEOAS and found them a pain to work with from a programmatic perspective.
If you ask me, REST is successful not because of any specific ruleset but because it is simpler than what came before it. It is the idea of REST that people like. I doubt most people actually know the full story!
Look at that, you've got me challenging Roy Fielding!
Per-resource versioning via the query-string is something I looked into but dismissed for schema flexibility reasons. To me, versioning sits at the protocol level (i.e. my service protocol, not to be confused with HTTP). If we decide to split "users" into two different resources e.g. "accounts" and "personas" then having a clean root to branch away from seems preferable.
I find the argument that "the URL is the resource, therefore the version shouldn't be part of it" to be somewhat self-entangled. The same argument surely applies to the protocol scheme and hostname. HTTP may not be the only protocol you want to publish resources over (perhaps you're developing a game with a dedicated UDP endpoint) and taking a full HTTP URL as your resource identifier is not conducive to interop! Rebranding may also move your resources even though they are the same resources. A resource identifier is a far more specific thing in my mind, and certainly shouldn't include the mechanism by which you access it as part of its identifier.
Anyway, as you say, the solution needs to fit the circumstances. We can agree on that much! There is no one-size-fits-all.
Thanks again for sharing your experience, I appreciate the advice.
Regards,
Ross.

I have no qualms about people being pragmatic when it comes to building services. If you've never read Fielding's dissertation, I recommend it. It's not that long and there is so much in there that holds true today. The part about REST is actually very short.  HTTP is actually but one, if the most prolific, example.

The Code REST is more what you call guidelines, than actual rules...

HATEOAS can be very effective, when done right. Sadly, I've see it done wrong many times. I happen to be an OData advocate and it's one of the few complete protocols that includes strong support for implementing HATEOAS. I agree that there is generally no practical way to make HTTP clients auto-magically do the next thing outside of a browser. While generating hyperlinks is convenient, I think the real value is knowing whether a resource can perform an action as opposed to what action link is (which most clients know in API development). For example, if api/orders/123 advertises link DELETE api/order/123 as a way to cancel an order. The fact that the link is advertised at all is the server telling the client that the action is available. The link and advertisement together can be really useful, but does not determine the success or completeness of an API.
The term URL tends to be highly overloaded. When I use it in the context of identification, I only mean the path. Everything else is additional metadata. Hostnames usually don't come into the picture, but the could. (ex: INT vs PROD resource). I agree with your assertion about protocols. The protocol is indicating how to get something, not what to get.
Thanks for all the input and feedback. It's interesting on a personal level and also helps fuel knowledge back to the community about why service authors choose the path they do. There are many strong opinion out there. I certainly have mine, but when people arrive here for advice I try to convey the reasons why service authors make the choices they do. Thanks for your contribution.
Hopefully I've demonstrated a path that works for you. If you're wondering what the remaining value propositions are, it will largely be the ancillary features like version advertisement, Swagger integration, etc. If you don't care about that or you have your own way of providing that, more power to you. :)
Good luck with your API.

Chris

Thanks again Chris. I have achieved what I need to for now.
Feel free to close the issue - I'm not sure what the etiquette is, is that my job or yours?!

I like to keep my issues low because I can't manage huge lists alone. I don't know that there is an official etiquette, but I give people 3-4 weeks to close their own issues - since they opened the issue. If not, I tend to close them off myself. If I think the issue might still be open, I usually ping the thread and give it up to a week.
Thanks again for your thoughts.


Update WordPress to 5.5.1

Sorry I already updated to WordPress 5.5.1 myself, this is not needed anymore.


Deprecate FHIRCore CustomPhotoCapture widget

Describe the Issue
Safely deprecate CustomPhotoCapture in favor of the SDK Attachment widget.
The Android FHIR SDK has added support for Attachment widget, it's features are:

More file types supported: image, document, audio and video files
Can limit file size
Can upload image from camera
Can upload file from Android File Selector
More enhancement coming

UI https://github.com/google/android-fhir/issues/1796
Multi attachment https://github.com/google/android-fhir/issues/1797
OOM preventation for large file https://github.com/google/android-fhir/issues/1797#issuecomment-1380179838

The FHIR Core CustomPhotoCapture widget is essentially an attachment widget but it only support uploading image from camera.
https://github.com/opensrp/fhircore/blob/main/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/CustomPhotoCaptureFactory.kt

Also, make sure the data capture dependency are up to date and has the new Attachment widget

cc @f-odhiambo

Kindly also manually test all Questionnaires that uses this widget, including those from our clients. Make sure it all works.
@f-odhiambo can help collecting which Questionnaires to test

Closed via #2098


Bind the edit program API with the view

Purpose

The purpose of this PR is to fix #26

Goals

Edit program details using the dashboard

Approach

Bound the API with the edit program view

Screenshots

Checklist

[x] This PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.
[x] I have read and understood the development best practices guidelines ( http://bit.ly/sef-best-practices )
[x] My code follows the style guidelines of this project
[x] I have performed a self-review of my own code
[x] I have commented my code, particularly in hard-to-understand areas
[ ] I have made corresponding changes to the documentation

Please fix the #27 with this pr too

Please fix the #27 with this pr too

No pressure. Only if you could


Invoice Compliance Check include egs_uuid which is wrong

I'm requesting ZATCA invoice compliance check API with UUID generated for my device,
But the invoiceXML is using another generated UUID,
So the API return the following error:
"errorMessages": [
      {
        "type": "ERROR",
        "code": "INVOICE_UUID_VALIDATION",
        "category": "MISSING_UUID_IN_INVOICE",
        "message": "UUID provided in the invoice doesn't match UUID in the provided Request",
        "status": "ERROR"
      },

Just a question now: Do we add a unique UUID per each invoice, or it's only 1 UUID per each EGS generating invoices ?

@marwan2 Every Invoice will have separate UUID

@marwan2 each EGS has its own UUID. Also, each invoice has its own UUID in this lib case the UUID for the invoice is the invoice counter number which is just an index that increases per invoice. e.g: 1, 2, ..
However, I'm not sure what's causing the error you have without the invoice and request details.


[RHOAIENG-591] - Add InstascaleMachineSet test

RHOAIENG-591

Closed as the required jira is closed now - https://issues.redhat.com/browse/RHOAIENG-591


Urls not produced when you use a RouteAttribute instead of using routes.MapRoute()

If I decorate my controllers and actions with the Route attributes built into MVC, in place of manually building out the routes via routes.MapRoute(), the provider doesn't seem to find or use the routes.  When using the Route attributes, the Url for each product we build with the dynamic node all have # as the value.
Dynamic Node
foreach(var prod in cat.Products)
{
    var prodNode = new DynamicNode();
    prodNode.Title = prod.Name;
    prodNode.ParentKey = catNode.Key;
    prodNode.Key = string.Format("Product_{0}", prod.Id);
    prodNode.Attributes.Add("visible", false);
    prodNode.Controller = "Product";
    prodNode.Action = "Index";
    prodNode.Route = "ProductInfo";
    prodNode.RouteValues.Add("id", prod.Id);
    prodNode.RouteValues.Add("producttitle", prod.Name);
}

Example not working:
public class RouteConfig
{
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapMvcAttributeRoutes();
            ...
        }
}

[RoutePrefix("product")]
public class ProductController : Controller
{
    // GET: product/123/pepsi
    [Route("{id}/{producttitle}", Name ="ProductInfo")]
    public ActionResult Index(int id)
    {
        ...
    }
}

Example working:
public class RouteConfig
{
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "ProductInfo",
                "product/{id}/{producttitle}",
                new { controller = "Product", action = "Index" }
                );
            ...
        }
}

public class ProductController : Controller
{
    // GET: product/123/pepsi
    public ActionResult Index(int id)
    {
        ...
    }
}

What happens if you remove/comment the route name for the non-working example?
//prodNode.Route = "ProductInfo";

Attribute Routing support was added as a contribution to MvcSiteMapProvider after MVC 5 was released, and it is possible that some of the features of it aren't fully supported.

Has no affect, still doesn't work.

 Is the code on the backend not calling Url.RouteUrl?
var url = new System.Web.Mvc.UrlHelper(HttpContext.Current.Request.RequestContext, System.Web.Routing.RouteTable.Routes);

foreach(var prod in cat.Products)
{
    var prodNode = new DynamicNode();
    prodNode.Title = prod.Name;
    prodNode.ParentKey = catNode.Key;
    prodNode.Key = string.Format("Product_{0}", prod.Id);
    prodNode.Attributes.Add("visible", false);
    prodNode.Controller = "Product";
    prodNode.Action = "Index";
    prodNode.Route = "ProductInfo";
    prodNode.RouteValues.Add("id", prod.Id);
    prodNode.RouteValues.Add("producttitle", prod.Name);
    prodNode.Url = url.RouteUrl("ProductInfo", new { id = prod.Id, producttitle = prod.Name });
}

Any updates?

So the issue turns out to be that the CurrentNode is always null when viewing a action that is created via attributes. I think I have traced it down to the FindSiteMapNodeFromMvcRoute method in the SiteMap.cs file.  It looks like GetMvcRouteData returns the underlining route when contained in a RouteCollectionRoute, and then that value is passed to the FindSiteMapNodeFromMvcRoute. In FindSiteMapNodeFromMvcRoute it runs through all the routes on the RouteTable.Routes and checks to see if each is equal to the passed in Route. Since the RouteTable.Routes doesn't have the sub route in it's root list, it always equals false. It might need to be changed up so that it doesn't do a straight object == object, and maybe check the route path or something.


⚠ Bofrost.es has degraded performance

In 87d317c, Bofrost.es (https://www.bofrost.es) experienced degraded performance:

HTTP code: 200
Response time: 1404 ms

Resolved: Bofrost.es performance has improved in 53d787c.


[Bug] TutorLeaderboardService#getExerciseLeaderboard Internal Server Error

Describe the bug
When trying to access the exercise assessment dashboard for an exam exercise an Internal Server Error is thrown:
2021-02-02 13:38:33.091 ERROR 20620 --- [nio-8081-exec-7] o.z.problem.spring.common.AdviceTraits   : Internal Server Error
org.springframework.orm.jpa.JpaSystemException: could not extract ResultSet; nested exception is org.hibernate.exception.GenericJDBCException: could not extract ResultSet

To Reproduce

Access an exam with submissions
Click on assessments
Select an exercise
See error
The exercise status also does not load correctly as a result of the above error

Expected behavior
No console error should be thrown apart from the 404 no submissions without results found
Screenshots

Environment

OS: [Windows 10]
Browser [Brave, Chromium: 88.0.4324.96 (Official Build) (64-bit)]
Version [1.19.88]

Additional context
I expect this to also be the case for course exercises, but did not try it out.
Output in Web Console

@anditurdiu Yeah, this bug is a general bug right now. #2807 Should fix it :)