feature: Add Avo admin panel

This PR adds Avo to Bullet Train as the default admin panel.
I configured four resources: User, Team, Membership, and Invitation with a few sensible starter fields.
If current_user.is_developer? they can access the admin at /avo.
Supersedes https://github.com/bullet-train-co/bullet_train/pull/794

@adrianthedev would you mind rebasing this against the current main branch? That might clear up the CI failures you're seeing.

@jagthedrummer I'm not sure if I should run bundle update capybara on this PR.
Downloading capybara-3.39.0 revealed dependencies not in the API or the lockfile
(nokogiri (~> 1.8)).
Running `bundle update capybara` should fix the problem.

Exited with code exit status 34

Ok. I did a proper rebase...

Hey @adrianthedev, I just pulled this branch down and am poking around at the /avo area. This is my first encounter with Avo, so I apologize if this is a dumb question/concern.
I'm a little concerned about how it would perform for busy apps. I'm looking at the "Edit Membership" screen for instance, and it has select elements for both team and user and it looks like it pre-loads every team and user into those lists. Do you know how this performs against large, active apps? Like if there are 10k users and 2k teams, it seem like that screen would take forever to load and would probably cause system degradation while it was loading.

No worries @jagthedrummer.  I love all the feedback.
That's correct. That wouldn't perform well.
The fix there is to add searchable: true to that field. That will not load any records but bring up a search interface to find those records.
I probably should add it though.

Ah-ha! I'm glad to hear that there's an easy fix. Other than that I think it's worth mentioning that the search field doesn't work, and I can see errors coming through the backend.

This is something that I'd like to go over with you. So we use ransack for search. It's in the Gemfile, but commented out.
If we enable ransack we should also add ransackable_attributes to the models in order to make them searchable.
What do you advise to do? Enable ransack in the Gemfile and have the search working or disable the search in Avo (comment out the code that configures the search) and let the users enable it when they need it?

🤔 Hmm... lemme think about that a bit. Neither option just jumps out as being the obviously correct one.

Yes. The searchable option is using the search and the users' configured search_query.
See the Course on Course Link in the avodemo app here and the corresponding source code.

OK, @adrianthedev I think that info makes an obvious choice stand out.
I think we definitely don't want to ship an implementation of Avo that includes pre-loaded select lists. So that means we need to include ransack anyway, which means that we may as well enable the default search and make everything searchable.

I pushed a chunkier commit which updates Avo to 3.0.1.beta.7. It's stable and ready for the public.
I'll push updates when we increment the version number to GA.
For full disclosure, the searchable field option is available in the Pro tier. I enabled it in the resource, and it will gracefully fallback to a regular select for the Community (free) tier which is installed by default.
I enabled the search for all resources.
The downside is that ransack now requires all models to have the ransackable_attributes method as a security measure.
I think you don't want to "muddle" up the models and offer clean models to those installing BT.
I have thought about what we could do here:

Use indirection and hide the methods under the Base modules
Use indirection and hide the methods under a different Ransack|Search|Admin concern
Add a new Concern and extend it from the avo.rb initializer

Example for 3.
module UserExtensions
  extend ActiveSupport::Concern

  def self.ransackable_attributes()
    ...
  end
end
Rails.configuration.to_prepare do
  User.include UserExtensions
end

I would choose 1. but will follow your advice.

Hey @adrianthedev, let me give this a little more thought. The added info about searchable only being available in Avo Pro has me reconsidering whether we should have that included and turned on by default. Let me think through the implications of that and I'll get back to you soon.

Generally, it takes a while until anyone needs the searchable option, and usually they have enough traction to switch over to Pro.
Sure, let me know if I can answer any more questions.

Hey @adrianthedev, first of all, I'm sorry to have started all of the back and forth over this.
I'm just laying out my current thoughts here so maybe you and @andrewculver can help guide this PR in for a landing.
Given the new info that searchable is only available in the Pro package I'm now leaning towards the idea that we shouldn't directly include any of the searchable/ransack stuff. Just to keep everything as simple as possible for the functionality that we actually ship.
Whatever we decide on that question I think we'll want to add a page to the documentation site that lets people know that Avo is part of the BulletTrain package and how they can get into it. There we should also mention how they can configure their own custom models to be available to Avo (can/should we make super scaffolding do this automatically and/or with a dedicated task). As part of that page we could also include a mention of Avo Pro, tell people why they might want to upgrade, and then have some instructions on how to upgrade to get the most benefit. Like telling them they need to install ransack and configure it, and anything else that they might need to do. (It might me as simple as linking to some existing Avo Pro docs.)
I think then we might leave the choice of where to put the ransackable_attributes up to the developer. We could list the options that you described above, and give recommendations on how to decide which to use.
Again, this is just me kind of thinking out loud, and I'm open to suggestion/persuasion. What do y'all think?

Hey @jagthedrummer.
Apologies for the delay. I went on vacation and then the conference season started, and just about now I'm getting to the bottom of my backlog.
I couldn't agree more with what you wrote.
Let's just ship something that brings immediate value to users.
We have everything rather well-documented and they can find their way fast to the searchable docs page.
Please direct me to the repository with the docs and I'll gladly write a page about this integration and how users should continue with Avo and BT.
I'd love to span this integration further and automatically expose super scaffolding commands to Avo resources. That's the experience I'd love to give to users.
I removed the ransack bits and commented out the search functionality for now.
As far as I'm concerned this PR is just perfect for the initial iteration.
So yeah, looking forward to your feedback @jagthedrummer and @andrewculver.
Thank you ✌

@adrianthedev, now it's my turn to apologize for the long delay! 😬 Somehow this managed to sneak past me. I'll try to give this a good look later this week and hopefully we can get it merged.
To answer your question about the docs, they live in the core repo inside the main bullet_train gem: https://github.com/bullet-train-co/bullet_train-core/tree/main/bullet_train/docs
Those markdown files correspond directly to the pages on the docs site: https://bullettrain.co/docs

No worries @jagthedrummer. Thank you for taking the time to review it.
I'll make time in the next few days to update the docs too.

No worries @jagthedrummer. Thank you for taking the time to review it.
I'll make time in the next few days to update the docs too.

@adrianthedev, would you mind doing a full rebase on this and making sure that you've updated avo in Gemfile.lock to the latest version?
As a last check before merging I pulled down this branch and rebased it, and rather than resolving conflicts in Gemfile.lock by hand I just checked out the HEAD version of that file and then did a bundle install which got me to avo 3.1.6. I pushed that to GitHub to let CI run, and CI is failing with a complaint about a tabs_style config option.
NoMethodError: undefined method `tabs_style=' for #<Avo::Configuration:...
# snip
>> (NoMethodError)

  config.tabs_style = :pills
        ^^^^^^^^^^^^^
/home/runner/work/bullet_train/bullet_train/tmp/starter/config/initializers/avo.rb:67

https://github.com/bullet-train-co/bullet_train/actions/runs/7198334742/job/19607520823?pr=1241
When I try to run the app locally it fails with the same error. I tried commenting out that line and then I get complaints about license_key and fields.
Seems that the initializer in this PR isn't up to date with the latest expectations of avo.
Relatedly, we have depfu set up on this repo to automatically bump gems if possible when new versions are released. Given that there's a decent amount of integration code in this PR should we pin avo to a more specific version?
I guess the real underlying question is more about the stability of the interfaces that are used in this PR. Do you expect them to be stable? In which case we could probably let the version float. Or are you still making developer-facing API level changes? In which case we should probably pin to at least a major version, if not minor.

Done! Rebased.
I'm not sure why the initializer was off like that (the tabs_style issue). Probably from a borked rebase.
It should be ok now.
Regarding breaking changes in the API, we do occasionally ship those. It's mostly to improve past mistakes.
With Avo 3 launched, we expect those to be far less than before as we made the API more consistent.
We have a thorough process of documenting breaking changes on our documentation website (v2 and v3).
We also have a two-week release cycle where we document everything we ship.
We don't follow semver but increment the minor version every two weeks and the patch version only when we ship quick bug fixes and for security updates.
My recommendation is not to pin it down Avo because the configuration files that BT ships have a very established API that's not prone to changes.
We will monitor and bring updates as we document them, but as I said, I don't foresee changes to this API.
Avo being so "alive" with so many new features every month, pinning down the version will almost make unpinning the version a default for users who want to use it.
I will default to your choice, though.

Yes, I think it's reasonable. I clicked commit pretty fast, but now I'm even pondering the /admin route.
I think /developers route might give some non-developer folks the heebie-jeebies that maybe they are not allowed there or that maybe they should mess things up.
I mean, my vision for this is to really enable the whole team (not just devs) to use it in production.
What do you think?

Well, on the one hand someone absolutely could mess things up via avo...
But I do see what you mean about it being aimed at a larger group than strictly "developers".
🤔

Thanks for the PR, @adrianthedev! I agree that we should not pin avo in the Gemfile. Gonna merge it and release a new version. 🚀

@jagthedrummer thank you for your time and support with this PR!
It means a lot for us to have Avo as the default admin panel in Bullet Train.
One note on the path. What do you think about having just /admin point to Avo directly.
I think people are used to (and some expect it) to have the /admin path take them to the admin panel.
I'm going to get started on those docs.
Thanks again @jagthedrummer and @andrewculver for your support!

@adrianthedev, I had considered just /admin but then thought "what if there are other admin type things that we/developers would like to put into the admin route space?" Maybe we should put a landing page at /admin that has a link to /admin/avo. Or maybe just a redirect for now.

That's a good question! Not really so obvious.
There are a couple of scenarios:

You are using the Community (free) tier

You can pass the project without any limitations to the customer as Avo Community is LGPL v3, an Open Source Initiative approved license

You are using Avo on the Pro or Advanced tiers

You can pass that license to your customer where they can take ownership of it and maintain the subscription in order to get updates.
If they don't want to maintain the subscription, they get to keep the version that they are on indefinitely.
So you, and your customer should be future-proofed in terms of licensing.
I'm here if I can answer any other questions.


location-based predictions and improvements

There's lots of things we could do by using the device's location, e.g.:

Capture spatial/geographic relationship of maps to each other.
When placing an issue, use the location of the device to estimate the desired position.
GPS/Altitude correlation: by recording the user's location when recording issues, the app can find out the locations of the maps and use that information to suggest relevant maps to the user, removing navigation effort (e.g. suggesting the closest map when launching the app).

Moved to Trello.


Api modify

Coverage decreased (-0.02%) to 46.033% when pulling 17f35fab1a0139bae9eb954d7df1564fc7707b27 on yuye/passwordChangeFix into 6724cf3c1112f22348a871591655b603c2b319c0 on authndev.


Fix ssao shader compilation bug

https://forum.babylonjs.com/t/pbrmaterial-and-missing-shaders/53062/10

Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s).
To prevent this PR from going to the changelog marked it with the "skip changelog" label.

Snapshot stored with reference name:
refs/pull/15500/merge
Test environment:
https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/refs/pull/15500/merge/index.html
To test a playground add it to the URL, for example:
https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/refs/pull/15500/merge/index.html#WGZLGJ#4600
Links to test babylon tools with this snapshot:
https://playground.babylonjs.com/?snapshot=refs/pull/15500/merge
https://sandbox.babylonjs.com/?snapshot=refs/pull/15500/merge
https://gui.babylonjs.com/?snapshot=refs/pull/15500/merge
https://nme.babylonjs.com/?snapshot=refs/pull/15500/merge
To test the snapshot in the playground with a playground ID add it after the snapshot query string:
https://playground.babylonjs.com/?snapshot=refs/pull/15500/merge#BCU1XR#0

WebGL2 visualization test reporter:
https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/refs/pull/15500/merge/testResults/webgl2playwright/index.html

Visualization tests for WebGPU (Experimental)
https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/refs/pull/15500/merge/testResults/webgpuplaywright/index.html


Hallway1 crashes the app

If you try to add the Hallway1 tile to the map editor, it becomes blank and an exception is generated inside the debug log file.
The cause is that, inside Mom\mom1e\tiles.ini the tag
[TileSideHallway1]
image="img/Tile_Hallway_1_MAD01.dds"
traits=inside small hallway
reverse=TileSideCrypt
is incorrect because the image should be a jpg file. so replacing .dds with .jpg should solve the problem
additionally the PPS should be set so
pps=72
is needed too.

Solved locally. Corrections will be included in my next localization pull request

Cherry picked to separate issue from pull request.


nnn: 3.6 → 4.0

Motivation for this change

Changelog
Add utils to PATH

Things done

[ ] Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
Built on platform(s)

[x] NixOS
[ ] macOS
[ ] other Linux distributions

[ ] Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
[ ] Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
[x] Tested execution of all binary files (usually in ./result/bin/)
[ ] Determined the impact on package closure size (by running nix path-info -S before and after)
[ ] Ensured that relevant documentation is up to date
[x] Fits CONTRIBUTING.md.

Result of nixpkgs-review pr 119291 run on x86_64-linux 1

1 package built:

nnn


License not mentioned for AXIOM

License missing
Github repo missing for this project
@moedn

there seem to be different versions of the camera. I found AXIOM Beta on GitHub. However, some documentation is only available on their Wiki (as the user manual).
I fixed the file :)


Running terraform apply twice required for successful deployment

Please provide us with the following information:

This issue is for a: (mark with an x)
- [x] bug report -> please search issues before submitting
- [ ] feature request
- [ ] documentation issue or request
- [ ] regression (a behavior that used to work and stopped in a new release)

Minimal steps to reproduce
Setting up the resources from scratch results in an error for the terraform apply in the first round:
az login
terraform init
terraform plan
terraform apply

Any log messages given by the failure
makortsm@DESKTOP-KJ383PJ:~/databricks-observability/$ terraform apply
module.keyvault.data.azurerm_client_config.current: Reading...
module.keyvault.data.azurerm_client_config.current: Read complete after 0s [id=Y2xpZW50Q29uZmlncy9jbGllbnRJZD0wNGIwNzc5NS04ZGRiLTQ2MWEtYmJlZS0wMmY5ZTFiZjdiNDY7b2JqZWN0SWQ9MDFhNDlkMWYtYTQxNi00ODgxLTk1NzUtNWE3ODNlNzk4Nzc3O3N1YnNjcmlwdGlvbklkPWM5MGE4ZWM1LWE5YTYtNGFjYi05NzFkLTY2NzZmM2M3ZThkMjt0ZW5hbnRJZD0xNmIzYzAxMy1kMzAwLTQ2OGQtYWM2NC03ZWRhMDgyMGI2ZDM=]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create
 <= read (data resources)

Terraform will perform the following actions:

  # random_id.storage_account will be created
  + resource "random_id" "storage_account" {
      + b64_std     = (known after apply)
      + b64_url     = (known after apply)
      + byte_length = 8
      + dec         = (known after apply)
      + hex         = (known after apply)
      + id          = (known after apply)
    }

  # module.app-insights.azurerm_application_insights.default will be created
  + resource "azurerm_application_insights" "default" {
      + app_id                                = (known after apply)
      + application_type                      = "other"
      + connection_string                     = (sensitive value)
      + daily_data_cap_in_gb                  = (known after apply)
      + daily_data_cap_notifications_disabled = (known after apply)
      + disable_ip_masking                    = false
      + force_customer_storage_for_profiler   = false
      + id                                    = (known after apply)
      + instrumentation_key                   = (sensitive value)
      + internet_ingestion_enabled            = true
      + internet_query_enabled                = true
      + local_authentication_disabled         = false
      + location                              = "eastus"
      + name                                  = (known after apply)
      + resource_group_name                   = "rg-dbobs"
      + retention_in_days                     = 90
      + sampling_percentage                   = 100
      + workspace_id                          = (known after apply)
    }

  # module.app-insights.azurerm_log_analytics_workspace.default will be created
  + resource "azurerm_log_analytics_workspace" "default" {
      + allow_resource_only_permissions    = true
      + daily_quota_gb                     = -1
      + id                                 = (known after apply)
      + internet_ingestion_enabled         = true
      + internet_query_enabled             = true
      + local_authentication_disabled      = false
      + location                           = "eastus"
      + name                               = (known after apply)
      + primary_shared_key                 = (sensitive value)
      + reservation_capacity_in_gb_per_day = (known after apply)
      + resource_group_name                = "rg-dbobs"
      + retention_in_days                  = 30
      + secondary_shared_key               = (sensitive value)
      + sku                                = "PerGB2018"
      + workspace_id                       = (known after apply)
    }

  # module.databricks.data.azurerm_key_vault_secret.db-pw will be read during apply
  # (config refers to values not yet known)
 <= data "azurerm_key_vault_secret" "db-pw" {
      + content_type            = (known after apply)
      + expiration_date         = (known after apply)
      + id                      = (known after apply)
      + key_vault_id            = (known after apply)
      + name                    = "sql-server-password"
      + not_before_date         = (known after apply)
      + resource_id             = (known after apply)
      + resource_versionless_id = (known after apply)
      + tags                    = (known after apply)
      + value                   = (sensitive value)
      + versionless_id          = (known after apply)
    }

  # module.databricks.data.databricks_spark_version.latest_lts will be read during apply
  # (depends on a resource or a module with changes pending)
 <= data "databricks_spark_version" "latest_lts" {
      + id                = (known after apply)
      + long_term_support = true
    }

  # module.databricks.azurerm_databricks_workspace.adb will be created
  + resource "azurerm_databricks_workspace" "adb" {
      + customer_managed_key_enabled          = false
      + disk_encryption_set_id                = (known after apply)
      + id                                    = (known after apply)
      + infrastructure_encryption_enabled     = false
      + location                              = "eastus"
      + managed_disk_identity                 = (known after apply)
      + managed_resource_group_id             = (known after apply)
      + managed_resource_group_name           = (known after apply)
      + name                                  = (known after apply)
      + network_security_group_rules_required = (known after apply)
      + public_network_access_enabled         = true
      + resource_group_name                   = "rg-dbobs"
      + sku                                   = "standard"
      + storage_account_identity              = (known after apply)
      + workspace_id                          = (known after apply)
      + workspace_url                         = (known after apply)
    }

  # module.databricks.azurerm_storage_account.dbstorage will be created
  + resource "azurerm_storage_account" "dbstorage" {
      + access_tier                       = (known after apply)
      + account_kind                      = "StorageV2"
      + account_replication_type          = "LRS"
      + account_tier                      = "Standard"
      + allow_nested_items_to_be_public   = true
      + cross_tenant_replication_enabled  = true
      + default_to_oauth_authentication   = false
      + enable_https_traffic_only         = true
      + id                                = (known after apply)
      + infrastructure_encryption_enabled = false
      + is_hns_enabled                    = false
      + large_file_share_enabled          = (known after apply)
      + location                          = "eastus"
      + min_tls_version                   = "TLS1_2"
      + name                              = (known after apply)
      + nfsv3_enabled                     = false
      + primary_access_key                = (sensitive value)
      + primary_blob_connection_string    = (sensitive value)
      + primary_blob_endpoint             = (known after apply)
      + primary_blob_host                 = (known after apply)
      + primary_connection_string         = (sensitive value)
      + primary_dfs_endpoint              = (known after apply)
      + primary_dfs_host                  = (known after apply)
      + primary_file_endpoint             = (known after apply)
      + primary_file_host                 = (known after apply)
      + primary_location                  = (known after apply)
      + primary_queue_endpoint            = (known after apply)
      + primary_queue_host                = (known after apply)
      + primary_table_endpoint            = (known after apply)
      + primary_table_host                = (known after apply)
      + primary_web_endpoint              = (known after apply)
      + primary_web_host                  = (known after apply)
      + public_network_access_enabled     = true
      + queue_encryption_key_type         = "Service"
      + resource_group_name               = "rg-dbobs"
      + secondary_access_key              = (sensitive value)
      + secondary_blob_connection_string  = (sensitive value)
      + secondary_blob_endpoint           = (known after apply)
      + secondary_blob_host               = (known after apply)
      + secondary_connection_string       = (sensitive value)
      + secondary_dfs_endpoint            = (known after apply)
      + secondary_dfs_host                = (known after apply)
      + secondary_file_endpoint           = (known after apply)
      + secondary_file_host               = (known after apply)
      + secondary_location                = (known after apply)
      + secondary_queue_endpoint          = (known after apply)
      + secondary_queue_host              = (known after apply)
      + secondary_table_endpoint          = (known after apply)
      + secondary_table_host              = (known after apply)
      + secondary_web_endpoint            = (known after apply)
      + secondary_web_host                = (known after apply)
      + sftp_enabled                      = false
      + shared_access_key_enabled         = true
      + table_encryption_key_type         = "Service"
    }

  # module.databricks.azurerm_storage_container.dbstorage will be created
  + resource "azurerm_storage_container" "dbstorage" {
      + container_access_type   = "private"
      + has_immutability_policy = (known after apply)
      + has_legal_hold          = (known after apply)
      + id                      = (known after apply)
      + metadata                = (known after apply)
      + name                    = "data"
      + resource_manager_id     = (known after apply)
      + storage_account_name    = (known after apply)
    }

  # module.databricks.databricks_cluster.default will be created
  + resource "databricks_cluster" "default" {
      + autotermination_minutes      = 20
      + cluster_id                   = (known after apply)
      + cluster_name                 = "demo-cluster"
      + default_tags                 = (known after apply)
      + driver_instance_pool_id      = (known after apply)
      + driver_node_type_id          = (known after apply)
      + enable_elastic_disk          = (known after apply)
      + enable_local_disk_encryption = (known after apply)
      + id                           = (known after apply)
      + node_type_id                 = "Standard_DS3_v2"
      + num_workers                  = 0
      + spark_conf                   = (known after apply)
      + spark_env_vars               = (known after apply)
      + spark_version                = (known after apply)
      + state                        = (known after apply)
      + url                          = (known after apply)

      + autoscale {
          + max_workers = 3
          + min_workers = 2
        }

      + cluster_log_conf {
          + dbfs {
              + destination = "dbfs:/cluster-logs"
            }
        }

      + init_scripts {
          + dbfs {
              + destination = (known after apply)
            }
        }
    }

  # module.databricks.databricks_dbfs_file.agent will be created
  + resource "databricks_dbfs_file" "agent" {
      + dbfs_path = (known after apply)
      + file_size = (known after apply)
      + id        = (known after apply)
      + md5       = "different"
      + path      = "/observability/applicationinsights-agent.jar"
      + source    = "applicationinsights-agent.jar"
    }

  # module.databricks.databricks_dbfs_file.applicationinsights-driver-json will be created
  + resource "databricks_dbfs_file" "applicationinsights-driver-json" {
      + dbfs_path = (known after apply)
      + file_size = (known after apply)
      + id        = (known after apply)
      + md5       = "different"
      + path      = "/observability/applicationinsights-driver.json"
      + source    = "modules/databricks/applicationinsights-driver.json"
    }

  # module.databricks.databricks_dbfs_file.applicationinsights-executor-json will be created
  + resource "databricks_dbfs_file" "applicationinsights-executor-json" {
      + dbfs_path = (known after apply)
      + file_size = (known after apply)
      + id        = (known after apply)
      + md5       = "different"
      + path      = "/observability/applicationinsights-executor.json"
      + source    = "modules/databricks/applicationinsights-executor.json"
    }

  # module.databricks.databricks_dbfs_file.init-observability will be created
  + resource "databricks_dbfs_file" "init-observability" {
      + dbfs_path = (known after apply)
      + file_size = (known after apply)
      + id        = (known after apply)
      + md5       = "different"
      + path      = "/observability/init-observability.sh"
      + source    = "modules/databricks/init-observability.sh"
    }

  # module.databricks.databricks_dbfs_file.log4j2-properties will be created
  + resource "databricks_dbfs_file" "log4j2-properties" {
      + dbfs_path = (known after apply)
      + file_size = (known after apply)
      + id        = (known after apply)
      + md5       = "different"
      + path      = "/observability/log4j2.properties"
      + source    = "modules/databricks/log4j2.properties"
    }

  # module.databricks.databricks_library.opentelemetry will be created
  + resource "databricks_library" "opentelemetry" {
      + cluster_id = (known after apply)
      + id         = (known after apply)

      + pypi {
          + package = "azure-monitor-opentelemetry~=1.0.0"
        }
    }

  # module.databricks.databricks_notebook.sample-telemetry-notebook will be created
  + resource "databricks_notebook" "sample-telemetry-notebook" {
      + format      = "SOURCE"
      + id          = (known after apply)
      + md5         = "different"
      + object_id   = (known after apply)
      + object_type = (known after apply)
      + path        = "/Shared/sample-telemetry-notebook"
      + source      = "modules/databricks/notebooks/sample-telemetry-notebook.py"
      + url         = (known after apply)
    }

  # module.databricks.databricks_notebook.telemetry-helper will be created
  + resource "databricks_notebook" "telemetry-helper" {
      + format      = "SOURCE"
      + id          = (known after apply)
      + md5         = "different"
      + object_id   = (known after apply)
      + object_type = (known after apply)
      + path        = "/Shared/telemetry-helper"
      + source      = "modules/databricks/notebooks/telemetry-helper.py"
      + url         = (known after apply)
    }

  # module.databricks.databricks_secret.app-insights-connection-string will be created
  + resource "databricks_secret" "app-insights-connection-string" {
      + config_reference       = (known after apply)
      + id                     = (known after apply)
      + key                    = "app-insights-connection-string"
      + last_updated_timestamp = (known after apply)
      + scope                  = "terraform-demo-scope"
      + string_value           = (sensitive value)
    }

  # module.databricks.databricks_secret.metastore-password will be created
  + resource "databricks_secret" "metastore-password" {
      + config_reference       = (known after apply)
      + id                     = (known after apply)
      + key                    = "metastore-password"
      + last_updated_timestamp = (known after apply)
      + scope                  = "terraform-demo-scope"
      + string_value           = (sensitive value)
    }

  # module.databricks.databricks_secret.storage-key will be created
  + resource "databricks_secret" "storage-key" {
      + config_reference       = (known after apply)
      + id                     = (known after apply)
      + key                    = (known after apply)
      + last_updated_timestamp = (known after apply)
      + scope                  = "terraform-demo-scope"
      + string_value           = (sensitive value)
    }

  # module.databricks.databricks_secret_scope.default will be created
  + resource "databricks_secret_scope" "default" {
      + backend_type             = (known after apply)
      + id                       = (known after apply)
      + initial_manage_principal = "users"
      + name                     = "terraform-demo-scope"
    }

  # module.keyvault.azurerm_key_vault.adb_kv will be created
  + resource "azurerm_key_vault" "adb_kv" {
      + access_policy                 = [
          + {
              + object_id          = "01a49d1f-a416-4881-9575-5a783e798777"
              + secret_permissions = [
                  + "Get",
                  + "List",
                  + "Set",
                  + "Delete",
                  + "Recover",
                  + "Purge",
                ]
              + tenant_id          = "16b3c013-d300-468d-ac64-7eda0820b6d3"
            },
        ]
      + id                            = (known after apply)
      + location                      = "eastus"
      + name                          = (known after apply)
      + public_network_access_enabled = true
      + purge_protection_enabled      = false
      + resource_group_name           = "rg-dbobs"
      + sku_name                      = "standard"
      + soft_delete_retention_days    = 7
      + tenant_id                     = "16b3c013-d300-468d-ac64-7eda0820b6d3"
      + vault_uri                     = (known after apply)
    }

  # module.rg.azurerm_resource_group.rg will be created
  + resource "azurerm_resource_group" "rg" {
      + id       = (known after apply)
      + location = "eastus"
      + name     = "rg-dbobs"
    }

  # module.sql-database.azurerm_key_vault_secret.db_pw will be created
  + resource "azurerm_key_vault_secret" "db_pw" {
      + id                      = (known after apply)
      + key_vault_id            = (known after apply)
      + name                    = "sql-server-password"
      + resource_id             = (known after apply)
      + resource_versionless_id = (known after apply)
      + value                   = (sensitive value)
      + version                 = (known after apply)
      + versionless_id          = (known after apply)
    }

  # module.sql-database.azurerm_mssql_database.sql-db will be created
  + resource "azurerm_mssql_database" "sql-db" {
      + auto_pause_delay_in_minutes         = (known after apply)
      + collation                           = (known after apply)
      + create_mode                         = "Default"
      + creation_source_database_id         = (known after apply)
      + geo_backup_enabled                  = true
      + id                                  = (known after apply)
      + ledger_enabled                      = (known after apply)
      + license_type                        = (known after apply)
      + maintenance_configuration_name      = (known after apply)
      + max_size_gb                         = (known after apply)
      + min_capacity                        = (known after apply)
      + name                                = "metastoredb"
      + read_replica_count                  = (known after apply)
      + read_scale                          = (known after apply)
      + restore_point_in_time               = (known after apply)
      + sample_name                         = (known after apply)
      + server_id                           = (known after apply)
      + sku_name                            = "Basic"
      + storage_account_type                = "Geo"
      + transparent_data_encryption_enabled = true
      + zone_redundant                      = (known after apply)
    }

  # module.sql-database.azurerm_mssql_firewall_rule.azure-services will be created
  + resource "azurerm_mssql_firewall_rule" "azure-services" {
      + end_ip_address   = "<IP_ADDRESS>"
      + id               = (known after apply)
      + name             = "Allow"
      + server_id        = (known after apply)
      + start_ip_address = "<IP_ADDRESS>"
    }

  # module.sql-database.azurerm_mssql_server.sql-server will be created
  + resource "azurerm_mssql_server" "sql-server" {
      + administrator_login                  = (known after apply)
      + administrator_login_password         = (sensitive value)
      + connection_policy                    = "Default"
      + fully_qualified_domain_name          = (known after apply)
      + id                                   = (known after apply)
      + location                             = "eastus"
      + minimum_tls_version                  = "1.2"
      + name                                 = (known after apply)
      + outbound_network_restriction_enabled = false
      + primary_user_assigned_identity_id    = (known after apply)
      + public_network_access_enabled        = true
      + resource_group_name                  = "rg-dbobs"
      + restorable_dropped_database_ids      = (known after apply)
      + version                              = "12.0"
    }

  # module.sql-database.random_id.username will be created
  + resource "random_id" "username" {
      + b64_std     = (known after apply)
      + b64_url     = (known after apply)
      + byte_length = 6
      + dec         = (known after apply)
      + hex         = (known after apply)
      + id          = (known after apply)
    }

  # module.sql-database.random_password.password will be created
  + resource "random_password" "password" {
      + bcrypt_hash = (sensitive value)
      + id          = (known after apply)
      + length      = 30
      + lower       = true
      + min_lower   = 0
      + min_numeric = 0
      + min_special = 0
      + min_upper   = 0
      + number      = true
      + numeric     = true
      + result      = (sensitive value)
      + special     = true
      + upper       = true
    }

  # module.databricks.module.periodic-job.databricks_job.main will be created
  + resource "databricks_job" "main" {
      + always_running      = false
      + format              = (known after apply)
      + id                  = (known after apply)
      + max_concurrent_runs = 1
      + name                = "Periodic job"
      + url                 = (known after apply)

      + schedule {
          + pause_status           = (known after apply)
          + quartz_cron_expression = "0 * * * * ?"
          + timezone_id            = "UTC"
        }

      + task {
          + existing_cluster_id = (known after apply)
          + retry_on_timeout    = (known after apply)
          + task_key            = "a"

          + notebook_task {
              + notebook_path = "/Shared/sample-notebook"
            }
        }
    }

  # module.databricks.module.periodic-job.databricks_notebook.main will be created
  + resource "databricks_notebook" "main" {
      + format      = "SOURCE"
      + id          = (known after apply)
      + md5         = "different"
      + object_id   = (known after apply)
      + object_type = (known after apply)
      + path        = "/Shared/sample-notebook"
      + source      = "modules/databricks/notebook-job/../notebooks/sample-notebook.py"
      + url         = (known after apply)
    }

  # module.databricks.module.streaming-job.databricks_job.main will be created
  + resource "databricks_job" "main" {
      + always_running      = false
      + format              = (known after apply)
      + id                  = (known after apply)
      + max_concurrent_runs = 1
      + name                = "Streaming job"
      + url                 = (known after apply)

      + schedule {
          + pause_status           = (known after apply)
          + quartz_cron_expression = "0 * * * * ?"
          + timezone_id            = "UTC"
        }

      + task {
          + existing_cluster_id = (known after apply)
          + retry_on_timeout    = (known after apply)
          + task_key            = "a"

          + notebook_task {
              + notebook_path = "/Shared/sample-streaming-notebook"
            }
        }
    }

  # module.databricks.module.streaming-job.databricks_notebook.main will be created
  + resource "databricks_notebook" "main" {
      + format      = "SOURCE"
      + id          = (known after apply)
      + md5         = "different"
      + object_id   = (known after apply)
      + object_type = (known after apply)
      + path        = "/Shared/sample-streaming-notebook"
      + source      = "modules/databricks/notebook-job/../notebooks/sample-streaming-notebook.py"
      + url         = (known after apply)
    }

  # module.databricks.module.telemetry-job.databricks_job.main will be created
  + resource "databricks_job" "main" {
      + always_running      = false
      + format              = (known after apply)
      + id                  = (known after apply)
      + max_concurrent_runs = 1
      + name                = "Telemetry job"
      + url                 = (known after apply)

      + schedule {
          + pause_status           = (known after apply)
          + quartz_cron_expression = "0 * * * * ?"
          + timezone_id            = "UTC"
        }

      + task {
          + existing_cluster_id = (known after apply)
          + retry_on_timeout    = (known after apply)
          + task_key            = "a"

          + notebook_task {
              + notebook_path = "/Shared/sample-telemetry-caller"
            }
        }
    }

  # module.databricks.module.telemetry-job.databricks_notebook.main will be created
  + resource "databricks_notebook" "main" {
      + format      = "SOURCE"
      + id          = (known after apply)
      + md5         = "different"
      + object_id   = (known after apply)
      + object_type = (known after apply)
      + path        = "/Shared/sample-telemetry-caller"
      + source      = "modules/databricks/notebook-job/../notebooks/sample-telemetry-caller.py"
      + url         = (known after apply)
    }

Plan: 33 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + resource_group_name = "rg-dbobs"

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

   Running terraform apply once more results in a successful deployment after all, so consider adding this to a 'known issues' section.
OS and Version?
WSL Ubuntu-20.04
Versions
Mention any other details that might be useful

Exactly the same problem in the first run for me but 2nd run does not fix it though.
If I try it multiple times I then keep getting this error:
...
Plan: 14 to add, 0 to change, 0 to destroy.
│ Error: User not authorized
│
│   with module.databricks.data.databricks_spark_version.latest_lts,
│   on modules\databricks\main.tf line 9, in data "databricks_spark_version" "latest_lts":
│    9: data "databricks_spark_version" "latest_lts" {
│
I'm really looking forward to trying out this solution because it seems to exactly what I was looking for. However, since I'm not familiar with Terraform I'm kind of stuck here.

@triplebeta, did you try waiting a bit before running it for the second time? It might be a race condition because we're deploying and authenticating to Databricks in the same terraform run.

Tried to run it 8 times, up to 20 minutes after the initial run. Same result each time.
I've installed terraform using the instructions from here, so it uses an SP with the Contributor role. Some resources (databricks, keyvault, sql, storage etc)  show up properly in the resource group.
In enabled logging for terraform and this is what it shows:
2023-11-28T13:58:17.201+0100 [WARN]  Provider "registry.terraform.io/hashicorp/azurerm" produced an invalid plan for module.sql-database.azurerm_key_vault_secret.db_pw, but we are tolerating it because it is using the legacy plugin SDK.     The following problems may be the cause of any confusing errors from downstream operations:       - .tags: planned value cty.MapValEmpty(cty.String) for a non-computed attribute       - .content_type: planned value cty.StringVal("") for a non-computed attribute module.databricks.data.azurerm_key_vault_secret.db-pw: Reading... module.databricks.data.azurerm_key_vault_secret.db-pw: Read complete after 0s [id=https://kvdbobs1234566......vault.azure.net/secrets/sql-server-password/187229a42c134fdcab86e0653b52186c] 2023-11-28T13:58:17.494+0100 [INFO]  provider.terraform-provider-databricks_v1.14.3.exe: Refreshed OAuth token for https://management.azure.com/ from Azure CLI, which expires on 2023-11-28 14:46:32.000000: timestamp="2023-11-28T13:58:17.493+0100" 2023-11-28T13:58:17.810+0100 [INFO]  provider.terraform-provider-databricks_v1.14.3.exe: Using Azure CLI authentication with AAD tokens: timestamp="2023-11-28T13:58:17.810+0100" 2023-11-28T13:58:19.352+0100 [INFO]  provider.terraform-provider-databricks_v1.14.3.exe: Refreshed OAuth token for 2ff814a6-3304-4ab8-85cb-cd0e6f879c1d from Azure CLI, which expires on 2023-11-28 14:55:52.000000: timestamp="2023-11-28T13:58:19.352+0100" 2023-11-28T13:58:21.690+0100 [ERROR] provider.terraform-provider-databricks_v1.14.3.exe: Response contains error diagnostic: @caller=/home/runner/work/terraform-provider-databricks/terraform-provider-databricks/vendor/github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/diag/diagnostics.go:55 @module=sdk.proto tf_proto_version=5.3 tf_rpc=ReadDataSource tf_provider_addr=registry.terraform.io/databricks/databricks tf_req_id=ca58b70b-c379-ebae-6d6b-60e705311d58 diagnostic_detail="" diagnostic_severity=ERROR diagnostic_summary="User not authorized" tf_data_source_type=databricks_spark_version timestamp="2023-11-28T13:58:21.690+0100" 2023-11-28T13:58:21.691+0100 [ERROR] vertex "module.databricks.data.databricks_spark_version.latest_lts" error: User not authorized 2023-11-28T13:58:21.692+0100 [ERROR] vertex "module.databricks.data.databricks_spark_version.latest_lts (expand)" error: User not authorized

We should try splitting the deployment in two Terraform deployments (Azure resources, and Databricks resources) and see if that solves the problem. Any takers?

I want to give it a go, also an opportunity to learn some terraform.

UPDATE: Today I tried deploying the solution to a sandbox environment in our company and it worked flawlessly the very first run. Don't understand why but I can get started to test it and show it to colleagues. For me no more need to make changes.
If we choose to use this for real, we'll have to incorporate some parts into our own terraform scripts anyway to be compliant with the policies in our subscription.
Thanks for all you work setting up this sample, much appreciated!


Add UXKit

Write code that works on both, UIKit and AppKit. A set of
typealiases and helper categories to make code work w/
both, UIKit and AppKit.

Thanks! I can see there's a few of these coming in. Feel free to submit them all in one PR. Doesn't matter if they're all from different authors, or not yours. As long as they all go in the list. 👍

Ah, OK, wasn't sure whether you want o pick. I'll try to group them ;-)


Compile 32-bit Windows programs

I successfully compiled the program.
but it cannot running on 32-bit Windows.
how shoud I compiled with 32-bit windows OS compatible programs...
but it still can only running on 64-bit windows.
please help me,thank you.
My system is Windows10 64-bit ,Vs2017 and Node.js 8.2.0
@pmq20

To compile to 32-bit windows OS compatible programs on a 64-bit machine, you should use a x64 x32 cross compiling environment. You should be able to find it in your Start Menu after installing Visual Studio. Also, you have to use a 32-bit Node.js, because the arch information is detected via node -pe process.arch

I have compiled the 32-bit program successfully.
thanks again.

Can this be written in the readme or Wiki? This is useful information.

@cloverhap added in https://github.com/pmq20/node-packer/commit/3847bd2ea5f949a8f2de47da8ac2cc10c1ee638d


[Feature Request] Need baseURL for reverse proxy support

Description
We need a baseURL setting (like Radarr and Sonarr have).
Desired Behavior
Allow Jellyseerr to run on https://my.url.com/jellyseerr/.
Additional Context
No response
Code of Conduct

[X] I agree to follow Overseerr's Code of Conduct

Looks like there was a failed attempt to implement in https://github.com/sct/overseerr/pull/2383.

I wouldn't say failed really. It's just more hacky than we'd like since Next.js doesn't allow for changing the base URL after build time. But the PR worked just fine for as long as I was testing it.
There's a preview image for it if you guys wanna try it out (one image was accidentally made, so it's either this one or this one)

Hm someone on discord said they got baseurl working with swag

@ddimick I have the detailed instructions on how to get it to work as well if needed

@Fallenbagel please post instructions for the baseurl mod

So here's my conf. Mind you, this is just how I got it working, but there's other things you could fix if you wanted to, in my case, they are not running in the same docker network, so I had to pass it the .1.28 ip address, but you normally would just have the name overseerr in that spot. You can also change the /overseerr to /jellyseerr, I just left them as that.

set $app 'overseerr';

# Remove /overseerr path to pass to the app
rewrite ^/overseerr/?(.*)$ /$1 break;
proxy_pass http://<IP_ADDRESS>:5055; # NO TRAILING SLASH

# Redirect location headers
proxy_redirect ^ /$app;
proxy_redirect /setup /$app/setup;
proxy_redirect /login /$app/login;

# Sub filters to replace hardcoded paths
proxy_set_header Accept-Encoding "";
sub_filter_once off;
sub_filter_types *;
sub_filter 'href="/"' 'href="/$app"';
sub_filter 'href="/login"' 'href="/$app/login"';
sub_filter 'href:"/"' 'href:"/$app"';
sub_filter '/_next' '/$app/_next';
sub_filter '/api/v1' '/$app/api/v1';
sub_filter '/login/plex/loading' '/$app/login/plex/loading';
sub_filter '/images/' '/$app/images/';
sub_filter '/android-' '/$app/android-';
sub_filter '/apple-' '/$app/apple-';
sub_filter '/favicon' '/$app/favicon';
sub_filter '/logo_' '/$app/logo_';
sub_filter '/site.webmanifest' '/$app/site.webmanifest';

}
> the only bug I have noticed is that if you go to another page such as settings, and reload, it won't recognize where you are because you'd now be under domain.com/settings etc. I'm 90% sure fixing the proxy_redirect or the $app variable to the IP address would fix that in my case
> This is the settings in the app itself
> ![unknown-24.png](https://user-images.githubusercontent.com/98979876/187986691-7d942768-275d-4782-8a97-83bb6797f7ae.png)
> Make sure your proxy is working because if you enable proxy support, you can still go to the app via IP and port, but it will not save anything, so you will have to go back and change the setting in the config file if you accidentally lock yourself out.

@Fallenbagel your config was working great until recently. Login screen just loops now.

@Fallenbagel your config was working great until recently. Login screen just loops now.

Since Overseerr 1.30.0 which is 1.2.0 of jellyseerr, the config is now different.
https://github.com/sct/overseerr/issues/274#issuecomment-1279709298

Why am I the last person still using Apache?  Haha.
Anyone have any hints on getting Jellyseerr working with a baseurl in Apache?

You are not. I am stuck too, looking for an Apache solution

You are not. I am stuck too, looking for an Apache solution

In my limited knowledge of apache, isn't nginx and apache very similar in its configuration? 🤔
Maybe a translation to it could be achieved

I hope to see this feature in future versions. There's no way to set a baseurl inside jellyseerr. Ombi has this but not jellyseerr

I would also love to see this much needed feature added :)

Why cant the base URL just be implied from the application URL setting?

I'd be interested in this! I don't know TS/React enough to make the change myself

The current implementation disallows urls without a . in them. Why is the validity of a url being tested? This breaks local (and docker) functionality.

Although it is great (not to mention very helpful, thank you) to see a workaround with nginx via realtime rewrites, there are many other popular proxies. Apache, Caddy, Traefik, Caddy, Cloudflare, etc. People who use OAuth may also find their configurations more complicated than would be otherwise necessary.

I think proper support should simply be implemented. For those that host multiple services on a single domain needing different sub-paths this won't work (domain.com/radarr, domain.com/sonarr, etc.). The ability to override the useragent (if users request) would be nice too (Jellyfin still thinks it is Overseerr).

The useragent is fixed in develop.
As for subpath thing it's been a bit hard to implement due to

Next.js not allowing to change the base URL after build time.

I have made a workaround for Nginx thanks to the help of what has already been provided and some minor tweaks of my own.
This method makes use of the Overseerr Nginx proxy config as well as injecting HTML to the client to fix the path (this fixes relading the page).
Complete Nginx config
Below is what you would put within your Nginx config, it contains the Javascript that is to be injected into the clients webpage.

location ^~ /jellyseerr {

    set $app 'jellyseerr';

    # Remove /overseerr path to pass to the app

    rewrite ^/jellyseerr/?(.*)$ /$1 break;

    proxy_pass http://<IP_ADDRESS>:5055; # NO TRAILING SLASH

    # Redirect location headers

    proxy_redirect ^ /$app;

    proxy_redirect /setup /$app/setup;

    proxy_redirect /login /$app/login;

    # Sub filters to replace hardcoded paths

    proxy_set_header Accept-Encoding "";

    sub_filter_once off;

    sub_filter_types *;

    #https://stackoverflow.com/questions/19700871/how-to-inject-custom-content-via-nginx

    sub_filter '' '';

    sub_filter 'href="/"' 'href="/$app"';

    sub_filter 'href="/login"' 'href="/$app/login"';

    sub_filter 'href:"/"' 'href:"/$app"';

    sub_filter '\/_next' '\/$app\/_next';

    sub_filter '/_next' '/$app/_next';

    sub_filter '/api/v1' '/$app/api/v1';

    sub_filter '/login/plex/loading' '/$app/login/plex/loading';

    sub_filter '/images/' '/$app/images/';

    sub_filter '/android-' '/$app/android-';

    sub_filter '/apple-' '/$app/apple-';

    sub_filter '/favicon' '/$app/favicon';

    sub_filter '/logo_' '/$app/logo_';

    sub_filter '/site.webmanifest' '/$app/site.webmanifest';

}

Formatted Javascript:
Below is the formatted javascript for if you want to read how it works or modify it, you do not need to do anything with this if you have copied the config above.

//https://stackoverflow.com/questions/6390341/how-to-detect-if-url-has-changed-after-hash-in-javascript

(() => {

    let APP_PATH = "jellyseerr";

    let oldPushState = history.pushState;

    history.pushState = function pushState() {

        //Check if we need to fix the path (if it dosent start with /jellyseerr then we need to fix it)

        if (arguments[2] && !arguments[2].startsWith("/" + APP_PATH))

            arguments[2] = "/" + APP_PATH + arguments[2];

        let ret = oldPushState.apply(this, arguments);

        window.dispatchEvent(new Event('pushstate'));

        return ret;

    };

    let oldReplaceState = history.replaceState;

    history.replaceState = function replaceState() {

        //Check if we need to fix the path (if it dosent start with /jellyseerr then we need to fix it)

        if (arguments[2] && !arguments[2].startsWith("/" + APP_PATH))

            arguments[2] = "/" + APP_PATH + arguments[2];

        let ret = oldReplaceState.apply(this, arguments);

        window.dispatchEvent(new Event('replacestate'));

        return ret;

    };

    window.addEventListener('popstate', () => {

        console.log('popstate');

    });

})();

Doesn't work for me, 404 error page not found. I installed it via Docker

@caio1007 the workaround is different now. You can find the latest updated one in the pinned thread on our discord.

@caio1007 the workaround is different now. You can find the latest updated one in the pinned thread on our discord.

Damn. I didn't expect it to be this hard.  I didn't expect it to be this hard.  Reverse-proxies can be setup to pull directly from / and you can simply set a base href with links not beginning with /, this'll cause them to be relative, so it'd work regardless.

And what if my host does not allow that?

And what if my host does not allow that?

Define that? The base href stuff and not writing links with / prefixed? That's a Jellyseerr issue that can be fixed easily. If you're talking about configuring your reverse-proxy I don't know how you mean that they don't "allow that". The fact you're using a r-proxy to begin with would be baffling if you can't actually configure it. ???

Apologies, I am awful at explaining stuff. I use https://ultra.cc to host a Jellyfin server, I believe me trying to setup what you're describing would be against their TOS

And what if my host does not allow that?

Define that? The base href stuff and not writing links with / prefixed? That's a Jellyseerr issue that can be fixed easily. If you're talking about configuring your reverse-proxy I don't know how you mean that they don't "allow that". The fact you're using a r-proxy to begin with would be baffling if you can't actually configure it. ???

Apologies, I am awful at explaining stuff. I use https://ultra.cc to host a Jellyfin server, I believe me trying to setup what you're describing would be against their TOS

??? What does your host have to do with anything? This thread is about Jellyseerr and using a subpath instead of accessing via 80, 443, or some other port while using a reverse-proxy to provide a clean subpath instead.

Ultra.cc manages jellyseerr and creates the sub path by itself

Ultra.cc manages jellyseerr and creates the sub path by itself

...So what are you here for then?

They manage the web proxy not me, so the solution is impossible to implement for me until someone fixes in in the actual code of jellyseerr #669 was my first post, but then I was redirected to here since im blind and didn't see this one

Ultra.cc manages jellyseerr and creates the sub path by itself

...So what are you here for then?

They manage the web proxy not me, so the solution is impossible to implement for me until someone fixes in in the actual code of jellyseerr #669 was my first post, but then I was redirected to here since im blind and didn't see this one

Edit: Removed post after seeing #669 which was not at all obvious or known. There is nothing you can do, but my solution would fix that. All links need to be updated to remove / and that includes generated links. Then a setting needs to be configurable to edit base href, this would be set to whatever public endpoint you want. You'll need to wait. I doubt your host set up Jellyseerr under a subpath without knowing about that so I'm thinking you did that. Just move it back to a port for now.

I will simply show you this doc, which shows that it will come pre-installed under a subpath
https://docs.ultra.cc/books/jellyseerr/page/jellyseerr

Edit: Removed post after seeing #669 which was not at all obvious or known. There is nothing you can do, but my solution would fix that. All links need to be updated to remove / and that includes generated links. Then a setting needs to be configurable to edit base href, this would be set to whatever public endpoint you want. You'll need to wait. I doubt your host set up Jellyseerr under a subpath without knowing about that so I'm thinking you did that. Just move it back to a port for now.

Imo I don't think using base href would be good for a nextjs app. I have looked into a way to make subpath possible and I have found a solution. It's less hacky than the method that was tried before.
Basically using a dynamic segment that houses all the pages and using a middleware that looks for a subpath using the serverRuntimeConfig and redirecting. I have tried it on a fresh nextjs project but haven't yet looked into how viable it would be for a jellyseerr/overseerr rewrite to support it.

That's not a subpath. That's a subdomin.

I'm not sure if you're talking about the host I'm using, but if so, it is a subpath.
a subdomain would be "jellyseerr.example.com" whereas a subpath is "example.com/jellyseerr"
The host I use uses this format for domains
"username.servername.usbx.me/appname"
Which is not a subdomain.
Is there a technical explanation on why it's so hard to set the baseURI. Can there be a settings option for it that applies after restart? Pretty much every other application I use does it just fine. Sonarr, Radarr, qBittorrent, Jellyfin, Autobrr, file browser, etc.

I added a part that monitors the DOM to modify the href attributes, which means that the links displayed by the browser on hover are correct and opening in a new tab via click + wheel or ctrl + click works.
Nginx sub filter:
sub_filter '' '';

Formatted script:
(() => {
  const APP_PATH = "/jellyseerr";

  const oldPushState = history.pushState;
  history.pushState = function pushState() {
    //Check if we need to fix the path (if it dosent start with /jellyseerr then we need to fix it)
    if (arguments[2] && !arguments[2].startsWith(APP_PATH))
      arguments[2] = APP_PATH + arguments[2];

    const ret = oldPushState.apply(this, arguments);
    window.dispatchEvent(new Event("pushstate"));
    return ret;
  };

  const oldReplaceState = history.replaceState;
  history.replaceState = function replaceState() {
    //Check if we need to fix the path (if it dosent start with /jellyseerr then we need to fix it)
    if (arguments[2] && !arguments[2].startsWith(APP_PATH))
      arguments[2] = APP_PATH + arguments[2];

    const ret = oldReplaceState.apply(this, arguments);
    window.dispatchEvent(new Event("replacestate"));
    return ret;
  };

  window.addEventListener("popstate", () => {
    console.log("popstate");
  });

  function addPrefixToLinks() {
    document.querySelectorAll("a[href]").forEach((link) => {
      const href = link.getAttribute("href");
      if (href.startsWith("/") && !href.startsWith(APP_PATH)) {
        link.setAttribute("href", APP_PATH + href);
      }
    });
  }

  document.addEventListener("DOMContentLoaded", function () {
    const observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (mutation.addedNodes.length) {
          addPrefixToLinks();
        }
      });
    });

    observer.observe(document.body, {
      childList: true,
      subtree: true,
    });

    addPrefixToLinks();
  });
})();

I was setting up jellyseerr and am using traefik and spent the last day to get the rules to run it behind traefik.
I have not seen any issues till now with the below rules, but haven't used it fro too long yet so can't really be sure.
Maybe this helps further.
      - "traefik.http.middlewares.jellyseerr-rewriterelativelocation.plugin.traefik-plugin-rewrite-response-headers.rewrites.header=Location"
      - "traefik.http.middlewares.jellyseerr-rewriterelativelocation.plugin.traefik-plugin-rewrite-response-headers.rewrites.regex=^/(.+)$"
      - "traefik.http.middlewares.jellyseerr-rewriterelativelocation.plugin.traefik-plugin-rewrite-response-headers.rewrites.replacement=/jellyseerr/$1"

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[0].regex=href=\"/(.+?)?\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[0].replacement=href=\"/jellyseerr/$1\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[1].regex=src=\"/(.+?)?\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[1].replacement=src=\"/jellyseerr/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[2].regex=href:\"/(.*?)\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[2].replacement=href:\"/jellyseerr/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[3].regex=\"/api/(.*?)\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[3].replacement=\"/jellyseerr/api/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[4].regex=\"/_next/(.*?)\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[4].replacement=\"/jellyseerr/_next/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[5].regex=\"/images/(.*?)\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[5].replacement=\"/jellyseerr/images/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[6].regex=src:\"/(.*?)\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[6].replacement=src:\"/jellyseerr/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[7].regex=linkUrl:\"/(.*?)\""
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.rewrites[7].replacement=linkUrl:\"/jellyseerr/$1\""

      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.lastModified=true"
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.monitoring.types[0]=text/html"
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.monitoring.types[1]=application/javascript"
      - "traefik.http.middlewares.jellyseerr-rewritebody.plugin.rewrite-body.monitoring.types[2]=*/*"

This is ofcourse running in docker and from my compose file

Any final solutions for this issue ?
(I want to put jellyseerr on /jellyseerr/ endpoint in nginx)

Any final solutions for this issue ?
(I want to put jellyseerr on /jellyseerr/ endpoint in nginx)

We don't support subfolders. Discord has the working workaround for it

@Fallenbagel I managed to succeed in doing it using this guide:
https://docs.overseerr.dev/extending-overseerr/reverse-proxy

this worked for me :
`        # Jellyseerr
location ^~ /jellyseerr {
set $app 'jellyseerr';
        # Remove /jellyseerr path to pass to the app
        rewrite ^/jellyseerr/?(.*)$ /$1 break;
        proxy_pass http://<IP_ADDRESS>:5055; # NO TRAILING SLASH

        # Redirect location headers
        proxy_redirect ^ /$app;
        proxy_redirect /setup /$app/setup;
        proxy_redirect /login /$app/login;

        # Sub filters to replace hardcoded paths
        proxy_set_header Accept-Encoding "";
        sub_filter_once off;
        sub_filter_types *;
        sub_filter '' '';
        sub_filter 'href="/"' 'href="/$app"';
        sub_filter 'href="/login"' 'href="/$app/login"';
        sub_filter 'href:"/"' 'href:"/$app"';
        sub_filter '\/_next' '\/$app\/_next';
        sub_filter '/_next' '/$app/_next';
        sub_filter '/api/v1' '/$app/api/v1';
        sub_filter '/login/plex/loading' '/$app/login/plex/loading';
        sub_filter '/images/' '/$app/images/';
        sub_filter '/android-' '/$app/android-';
        sub_filter '/apple-' '/$app/apple-';
        sub_filter '/favicon' '/$app/favicon';
        sub_filter '/logo_' '/$app/logo_';
        sub_filter '/site.webmanifest' '/$app/site.webmanifest';
    }`

This worked for me :
...

this worked for me as well, thank you!

This worked for me :
       # Jellyseerr
        location ^~ /jellyseerr {
            set $app 'jellyseerr';

            # Remove /jellyseerr path to pass to the app
            rewrite ^/jellyseerr/?(.*)$ /$1 break;
            proxy_pass http://<IP_ADDRESS>:5055; # NO TRAILING SLASH

            # Redirect location headers
            proxy_redirect ^ /$app;
            proxy_redirect /setup /$app/setup;
            proxy_redirect /login /$app/login;

            # Sub filters to replace hardcoded paths
            proxy_set_header Accept-Encoding "";
            sub_filter_once off;
            sub_filter_types *;
            sub_filter '' '';
            sub_filter 'href="/"' 'href="/$app"';
            sub_filter 'href="/login"' 'href="/$app/login"';
            sub_filter 'href:"/"' 'href:"/$app"';
            sub_filter '\/_next' '\/$app\/_next';
            sub_filter '/_next' '/$app/_next';
            sub_filter '/api/v1' '/$app/api/v1';
            sub_filter '/login/plex/loading' '/$app/login/plex/loading';
            sub_filter '/images/' '/$app/images/';
            sub_filter '/android-' '/$app/android-';
            sub_filter '/apple-' '/$app/apple-';
            sub_filter '/favicon' '/$app/favicon';
            sub_filter '/logo_' '/$app/logo_';
            sub_filter '/site.webmanifest' '/$app/site.webmanifest';
        }

Used with SWAG, mostly works, but fails to load posters from /imageproxy/.

This worked for me :
       # Jellyseerr
        location ^~ /jellyseerr {
            set $app 'jellyseerr';

            # Remove /jellyseerr path to pass to the app
            rewrite ^/jellyseerr/?(.*)$ /$1 break;
            proxy_pass http://<IP_ADDRESS>:5055; # NO TRAILING SLASH

            # Redirect location headers
            proxy_redirect ^ /$app;
            proxy_redirect /setup /$app/setup;
            proxy_redirect /login /$app/login;

            # Sub filters to replace hardcoded paths
            proxy_set_header Accept-Encoding "";
            sub_filter_once off;
            sub_filter_types *;
            sub_filter '' '';
            sub_filter 'href="/"' 'href="/$app"';
            sub_filter 'href="/login"' 'href="/$app/login"';
            sub_filter 'href:"/"' 'href:"/$app"';
            sub_filter '\/_next' '\/$app\/_next';
            sub_filter '/_next' '/$app/_next';
            sub_filter '/api/v1' '/$app/api/v1';
            sub_filter '/login/plex/loading' '/$app/login/plex/loading';
            sub_filter '/images/' '/$app/images/';
            sub_filter '/android-' '/$app/android-';
            sub_filter '/apple-' '/$app/apple-';
            sub_filter '/favicon' '/$app/favicon';
            sub_filter '/logo_' '/$app/logo_';
            sub_filter '/site.webmanifest' '/$app/site.webmanifest';
        }

Used with SWAG, mostly works, but fails to load posters from /imageproxy/.
p.s. nvm, it works on develop version. But fails on latest (docker) for some reasons...

Develop is very different from stable

This surely will offend somone, the truth usually does.

We don't support subfolders. Discord has the working workaround for it

Just like some car manufacturers choose to not support wheels.
This is not a choice or opinion, you code is broken.
https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
That it works with subdomains doesn't mean it is "supported/implemented/working" it means it is just not yet also broken.
Strangely enough you know to develop containarized builds but don't realize they all mainly live behind proxies.

@Fallenbagel I managed to succeed in doing it using this guide: https://docs.overseerr.dev/extending-overseerr/reverse-proxy

This is not working, this is duct tape and make believe.

Then enlighten me on how we can support base urls when the tech stack that jellyseerr/overseerr uses, nextjs, doesnt support dynamic baseurls in runtime.
If you think this can be supported then why dont you create a pr to support this? We are all volunteers working on our free time to provide a FREE product.

Just like some car manufacturers choose to not support wheels.
This is not a choice or opinion, you code is broken.

Base URL is absolutely not necessary for Jellyseerr to be fully functional. And linking to the first Wikipedia article you find without understanding it to try to justify what you're saying makes absolutely no sense.
As Fallen said, we're just volunteers spending tens of hours every month to make Jellyseerr work the best we can. We owe you nothing.

Yes, a work-around would've been for Jellyseerr to add base href and set all URLs to relative including what NextJS outputs (simple patch) since it'd be just a few lines of code and an adjustment on their part of how they do links

That's the thing you don't understand. It's not "just a few lines of code".
Next.js performs a lot of optimizations during build time (i.e. static assets optimization, code splitting or server side rendering). That's also why Jellyseerr is quite fast despite being a fairly large web app. And you can't just do a "simple patch" to add base URLs to the outputs of Next.js.
The only thing that would work would be an option for users that are building the app from source, but it would not work for Docker users, and they are the majority of users.
If someone does have a reliable solution to implement base URLs, we would be glad to consider it, feel free to make a PR. But we didn't find any for now, we just found some tricks to make it work.

sorry for dropping into the conversation but doesn't nextjs already support this per https://nextjs.org/docs/app/api-reference/next-config-js/basePath ?

sorry for dropping into the conversation but doesn't nextjs already
support this per
https://nextjs.org/docs/app/api-reference/next-config-js/basePath ?

As far as i understand it- the keyword is "runtime" . You can use basePath
during build stage. So anyone who want to use it on subfolder, basically,
have to compile it from sources, or use tricky middleware.
It's fine for those who understand what they do, but most of userbase use
releases or docker containers.
вт, 10 дек. 2024 г. в 01:15, Adrian Popescu @.***>:

sorry for dropping into the conversation but doesn't nextjs already
support this per
https://nextjs.org/docs/app/api-reference/next-config-js/basePath ?
—
Reply to this email directly, view it on GitHub
https://github.com/Fallenbagel/jellyseerr/issues/97#issuecomment-2529643183,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AG34IYFZGKUQBFSBXV7AFOL2EYI65AVCNFSM5WR7HT52U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TENJSHE3DIMZRHAZQ
.
You are receiving this because you commented.Message ID:
@.***>

@Rumbiz this is a compile-time option, not a run-time option. Meaning that you'd need to rebuild the application from source to make it work. That's exactly what @gauthier-th mentioned before.

This project is entirely free and open source, driven by the dedication of its contributors. Contributions—whether through code, constructive feedback, or professional discussions—are always welcome and greatly appreciated.
That said, I kindly ask everyone to maintain a respectful and professional tone when engaging in this thread. Criticism is welcome when it's constructive, but any unprofessional comments that undermine the hard work of our contributors (including those of related projects like Overseerr) will not be tolerated.
This is a request for an optional feature—one we are committed to exploring despite current limitations. If there’s any confusion about what this entails, what these limitations are, and why implementing it in a hacky way (modifying compiled code) is bad, I advise you to look it up before undermining other's hardwork.
That said, this discussion is over for now.

This project is entirely free and open source, driven by the dedication of its contributors. Contributions, whether through code, constructive feedback, or professional discussions, are always welcome and greatly appreciated.
That said, I kindly ask everyone to maintain a respectful and professional tone when engaging in this thread. Criticism is welcome when it's constructive, but any unprofessional comments that undermine the hard work of our contributors (including those of related projects like Overseerr) will not be tolerated.
This is a request for an optional feature, one we are committed to exploring despite current limitations. If there’s any confusion about what this entails, what these limitations are, and why implementing it in a hacky way (modifying compiled code) is bad, I advise you to look it up before undermining other's hardwork.
That said, this discussion is over for now.

use of port 5055 rather than port 80.

That's literally the default port configuration. Every web service attaches to a port, which must be unique to avoid conflicts with other services.
If port 5055 doesnt suit your needs, you can easily change it by setting the PORT=80 environment variable.

perhaps you intend to implement subdomain-to-port application routing as an extension to the current "design of the internet"? For example, potato.domain.tld could go to port 4044, and tomato.domain.tld could go to port 5055 all on its own—maybe through some modern SNI implementation, similar to DNS over HTTPS (DoH).

There is no such thing as this, and this makes no sense. Web apps work by attaching to a default port, and reverse proxies handle routing requests to appropriate services. Typically, reverse proxies operate on port 80 (HTTP) or 443 (HTTPS). **Subdomains are not an application-level feature. They're handled at the DNS level and function as prefixes to your base domain while working exactly the same as a base domain. The internet inherently supports subdomains, and their behavior doesn't depend on application-specific code.
Regarding basepath: while they are a useful feature for consolidating services under one domain, they are not required for a fully functional web service. In this case, our framework (nextjs, I.e the tech stack we use) has limitations that prevent proper basepath support, as has been explained previously multiple times.
Your analogy of a car does not apply here as basepath is ENTIRELY, and COMPLETELY optional. It is not required to proxy your service. I would recommend reading up on this before making ill-informed comments (no offense).
This issue is a feature request to implement an OPTIONAL quality-of-life feature. The application already achieves its intended scope and supports proper proxying as any other self-hosted services. While we value constructive discussion on how to properly implement this, but off-topic comments and repeated misconceptions hinder the progress, and waste valuable time of others.
I do not want this issue discussion to be a place for education as it has come to be. And as there have not been any constructive discussion that are on-topic (except for a few informed comments above), that is not repeating the same nonsense, and my request to end this discussion was not properly respected and wasted the valuable time of everyone who are genuinely trying to contribute to the discussion, this thread will remain LOCKED until further notice.
I sincerely apologise to any of those who were looking to have a constructive discussion about this issue, and if you have any insights or want to discuss further on implementing basepath support given our framework, feel free to reach out to me via our discord server.


Missing mpii/pureannot/train.h5

After following the instruction, I ran command
python main.py -DataConfig conf/datasets/mpii.defconf -ModelConfig conf/models/ChainedPredictions.defconf
Got error:

File "/scratch/liu.shu/codesPool/Pytorch-Human-Pose-Estimation/datasets/mpii.py", line 22, in init
f = H.File('{}/mpii/pureannot/{}.h5'.format(self.opts.dataDir, split), 'r')
File "/home/liu.shu/.conda/envs/pch1.5/lib/python3.8/site-packages/h5py/_hl/files.py", line 406, in init
...
File "h5py/h5f.pyx", line 88, in h5py.h5f.open
OSError: Unable to open file (unable to open file: name = '/scratch/liu.shu/datasets/MPII/mpii/pureannot/train.h5', errno = 2, error message = 'No such file or directory', flags = 0, o_flags = 0)

I didn't see the instruction how to get the mpii/pureannot/train.h5.
Could you provide it?

You can download the h5 files from here .

Thanks.


Logging, simplified

Simplified by removing unused - and likely unneeded - functionality.  So just one logger, and easier to reset streams logged to.

Codecov Report

Merging #149 (4d0fed5) into master (a79e168) will decrease coverage by 0.01%.
The diff coverage is 88.88%.

@@            Coverage Diff             @@
##           master     #149      +/-   ##
==========================================
- Coverage   83.32%   83.31%   -0.02%
==========================================
  Files          67       67
  Lines        6052     6066      +14
==========================================
+ Hits         5043     5054      +11
- Misses       1009     1012       +3

Impacted Files
Coverage Δ

db/silkworm/common/tee.hpp
79.16% <55.55%> (-14.59%)
:arrow_down:

db/silkworm/common/log.cpp
100.00% <100.00%> (ø)

db/silkworm/common/log.hpp
100.00% <100.00%> (+10.00%)
:arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a79e168...4d0fed5. Read the comment docs.

Codecov Report

Merging #149 (4d0fed5) into master (a79e168) will decrease coverage by 0.01%.
The diff coverage is 88.88%.

@@            Coverage Diff             @@
##           master     #149      +/-   ##
==========================================
- Coverage   83.32%   83.31%   -0.02%
==========================================
  Files          67       67
  Lines        6052     6066      +14
==========================================
+ Hits         5043     5054      +11
- Misses       1009     1012       +3

Impacted Files
Coverage Δ

db/silkworm/common/tee.hpp
79.16% <55.55%> (-14.59%)
:arrow_down:

db/silkworm/common/log.cpp
100.00% <100.00%> (ø)

db/silkworm/common/log.hpp
100.00% <100.00%> (+10.00%)
:arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a79e168...4d0fed5. Read the comment docs.


Update docs & notes

This PR:

adds a Notes section to the docs
adds a note about a cool feature -> automatic gradient accumulation

Update: this PR requires a re-review. It now also:

adds a note on autoresumption
shortens some of the notebook names
moves some of the topics (e.g. precision) from trainer -> notes. Not sure the right demarcation here.


mobile

🤔 Check all before merging!

[ ] 📈Project board up to date
[ ] 🏗 Everything implemented thoroughly
[ ] 🔨 All changes tested

[ ] Change #1
[ ] Change #2...

[ ] 👀 Go through the diff
[ ] 📝 API changes included in README.md
[ ] 📣 Major changes listed in changelog.txt

✅ All good? -> Merge! 🎉🎉🎉

Hey, what are you trying to achieve? 🤔


Tabline weird symbol after name.

Hi,
when I open new buffers, some of them have a weird characters or symbols at the end after the name in the tabline:

How do I remove those chracters? The file is not named like that.
By the way all my airline settings are in the picture.
Thank you.

not sure, are you using other plugins?

By commenting back and forth my vimrc, I found the solution:
Remove 'let g:airline_powerline_fonts = 1' from the vimrc.
I did not notice it because I was using a theme that did not have any '>' after the file name, so I thought I wouldn’t have to use any powerline fonts.


TestSites only uses the name: contentType, which is not compatible with uppy.

uppy
Upload-Metadata: relativePath bnVsbA==,name Q2hyeXNhbnRoZW11bS5qcGc=,type aW1hZ2UvanBlZw==,filetype aW1hZ2UvanBlZw==,filename Q2hyeXNhbnRoZW11bS5qcGc=
error
contentType metadata must be specified.
TestSites
Upload-Metadata: name Q2hyeXNhbnRoZW11bS5qcGc=,contentType aW1hZ2UvanBlZw==,emptyMetaKey

I have no idea what you are asking here? The test sites are not supposed to be hard coded for Uppy but to show case how to validate whatever metadata that the server and client agrees upon. The tus protocol does not enforce any metadata and just leaves it to the server and client to decide.
If you look at the Startup class in each of the test sites you will see that it's just custom code that the developer can provide: https://github.com/tusdotnet/tusdotnet/blob/master/Source/TestSites/AspNetCore_netcoreapp3.1_TestApp/Startup.cs#L153


An error occurred while rendering the React Router 6 Modal

🐛 Bug report
Current Behavior
When refreshing the modal page:
Expected server HTML to contain a matching <div> in <div>.

Expected behavior
no error.
Reproducible example
react router official example
Suggested solution(s)
Additional context
Your environment

Software
Version(s)

Razzle
4.2.8

Razzle Plugins
4.2.8

Node
16

Browser
chrome

npm/Yarn
yarn

Operating System
macOS

TypeScript
4.5.2

React
17.0.2

React Router
6.0.2

I made a small modification to not use the routing state, and use the Modal as a normal page.
No problem now, you can close this.


theme deploy is oblivious to rate limiting + does not fail on errors

Describe the bug
Two issues with theme deploy which make it unreliable to use especially in CI:

There is apparently a rate limit on the underlying API - I'm really excited that at least I get to know what the limit is, it's 4 requests per second according to the logs printed out below. Anyway, issue 1 is that although it seems like Themekit could monitor for this, or any other failure, and handle it in some way (waiting a few seconds and retrying this file would be the most naïve approach, better would be to learn from the failure and after finding a delay that is long enough, to stick to that for the rest of the deploy).

Themekit just prints a message and continues running in this case. I can't think of any case where this is useful behavior. Assuming the above is too complex to implement, Themekit should absolutely exit immediately with code 1 anytime there is an error like this. This is just CLI standard practice as far as I've ever seen outside of Shopify tools. It will allow developers to implement their own error handling. Currently the only workaround I can imagine would be super wasteful: run theme deploy, capture entire output and grep for this kind of message (are there other kinds?) and if we found them, sleep a while and deploy the whole theme again, repeating with fingers crossed. It seems like at least adding an option to exit on failure would be a good idea.

...
[development] (snippets/a-form.liquid) Exceeded 4 calls per second for api client. Reduce request rates to resume uninterrupted service.
[development] Updated templates/page.liquid
[development] (assets/template.cart.css.liquid) Exceeded 4 calls per second for api client. Reduce request rates to resume uninterrupted service.
[development] Updated assets/template.collection.css.liquid
[development] (assets/template.blog.alt.js.map) Exceeded 4 calls per second for api client. Reduce request rates to resume uninterrupted service.
...

To Reproduce
Steps to reproduce the behavior:

run theme deploy --verbose on 2 theme folders uploading 2 different themes in 2 different windows concurrently on a fast connection
see errors like Exceeded 4 calls per second for api client....
cry

Expected behavior
Either back-off and retry asset or just exit 1 and let the user/script handle it
Environment (please complete the following information):

OS [e.g. iOS]: buster
Themekit version [e.g. v0.7.5]: whatever the latest version is, it doesn't seem to have a --version option

You are either using the same private app as another developer or your are running two instances because themekit has a whole section of code that actually does all of the rate limiting. It can only tell its own usage though so if you are in one of these other two scenarios, then you will have problems


[BUG][WCAG] requests/new - Little to no feedback on buttons to indicate focus.

Describe the bug
When the user hovers over or tabs into certain buttons on the requests/new page, there is either not enough of a change to the button or no change at all to indicate focus.
All elements with user interaction must indicate when it is in focus, whether by hovering over it with the cursor, or tabbing into the element with the keyboard.
1. Use my location: The colour does not change enough to be considered compliant when the user hovers over or tabs into this button.
Idle hex code: 7D00A3
Focused hex code: A12596
Minimum contrast requirement: 3:1
2. "Menu", "New request" and "Notification" buttons: There is NO feedback on any of these buttons.
Optional. "Search" and "Cancel" button text: The colour of the text does not have a very high contrast when hovered over. This is optional because the boarder of these buttons do change enough.
https://reach4help-staging-web-client.firebaseapp.com/requests/new
To Reproduce
Steps to reproduce the behavior:

Navigate to requests/new page.
Hover over each button.
3 (w/ Axe). Check hex codes of idle and focused buttons.
Notice that contrasts do not meet minimum requirements.
Notice that focusing over the menu, new request and notification buttons does nothing.

Expected behavior
Users are given proper feedback to indicate focus. Feedback include compliant contrast ratios.
Screenshots
Video posted in Slack team-user-testing channel.
https://slack-files.com/T010H81FF60-F015MQLBQ48-620cd65262
Desktop (please complete the following information):

Windows 10 - Chrome

Additional context
Two-color focus indicator techniques: https://www.w3.org/WAI/WCAG21/Techniques/css/C40
https://contrastchecker.com/
https://www.w3.org/WAI/WCAG21/quickref/#focus-visible

ZenHub Information
This information is updated automatically. To modify it, please use ZenHub.

ZenHub Information
This information is updated automatically. To modify it, please use ZenHub.

Most buttons on the Request/new page now gives the user feedback when hovered over or tabbed into.
Please note that while the main Menu buttons do have focus indicators, the X to close the drawer does not.
Also note that the Menu and Notification drawers do not have keyboard functionality. This ticket cannot be fully checked or closed until https://github.com/reach4help/reach4help/issues/649 is resolved.


Adding objects to perspectives by default

Whenever a column or measure is added to a table, it is easy to forget that the object often also needs to be added to the perspectives of the model.
It would be nice to have an option that new columns and measures being added to the model, are automatically included in all perspectives in which the parent table is already included.
So for example, if your model contains 3 perspectives (Logistics, Sales and HR), and the Sales table is already included in the "Sales" perspective, then, whenver you add a new measure to the Sales table, that measure will also automatically be included in the "Sales" perspective.
This option should be off by default (to avoid breaking existing workflows), but it should be possible to toggle this option on in the "Preferences" dialog.

As of 2.7.3, when a perspective is selected in the dropdown, new objects are added to that perspective by default.


Apple Magic Mouse Unexpected behaviour

With the latest version of Apple Magic Mouse and v0.7.5, when turning the mouse on or reconnecting the mouse to the Mac, the cursor speed is much much slower than expected. I would estimate Speed: 0 would be what it reverts to. It can be fixed by opening the LinearMouse application and will fix this instantly. This happens on login and every time the mouse is turned off and reconnected. It is quite annoying having to open the application every time to fix this.
Settings are "Acceleration": 0 and "Speed": 0.12, and "Disable pointer acceleration": Unchecked
MacBook M1 Air 2020 Edition Monterey 12.6

Can confirm I have auto switch to active device ticked and also have same issue as others, specific to Apple Magic Mouse 2 and not reproducible with any other wireless mice

Duplicates of #209, #280.
Looks like it's time for me to buy a Magic Mouse 2 :)

Fixed in v0.7.6-beta.1.


remove redundant PermissionsResultAction object in mPendingActions list, fixed a wrong callback issue

Hi, anthonycr
I'm using your lib for the runtime permissions request. Thanks for you great work!
I've found a issue when a permission is already granted, request another permission, the wrong callback method will be invoked.
I added some codes in your sample to reproduce this issue and then I add my solution in your lib to fix it.
Now it works well.
I'd like you take a look and merge it. Thanks!

Awesome, reviewing now.

 Thanks for finding, merging now.


fix: continuous event topic api calls

Part of #1689
Changes: change flowable similar events to single events.

@iamareebjamal now getting the events from db.

Changes:

Made event lists flowable (home, search, favourites, similar topic & location events)
Using Sets for similar topic events & location events because both can have mutual events
Calling api for similar topic events

Video (ignore the bg noise)
https://drive.google.com/file/d/1mTqwYZf6JNjaBXmxfDassxAs5NBRy3cE/view?usp=sharing
@iamareebjamal @anhanh11001 @liveHarshit @nikit19 review please


Missing strong name

Hi,
could you sign the assembly with a strong name please?
Best regards
Boris

I suggest you fork it and strong name your fork.
I don't strong name for the reasons at http://jeremydmiller.com/2014/04/28/fubumvc-lessons-learned-strong-naming-woes-and-workarounds/

https://github.com/Haacked/Rothko/pull/23


It pops an alert saying Topic is missing

I tried sending push but it shows an alert with 400 code and shows Topic is missing but I am not able to add topic since the field is disabled.

Same here, can't edit topic

Same here, can't edit topic

@Kushal-786 @nmtitov
It is a problem when using the development certification(aps_development.cer).
You can add the following code :
  if(0 == topic.length) {         topic = @"your app bundle id";     }
above the code:
if (topic) {         [request addValue:topic forHTTPHeaderField:@"apns-topic"];     }
Then, choose the development certification, fill in token, and click "Push" btn.
It works now!

I have fix topic error(400) by optimize user interaction:
https://github.com/Dast1Woop/Knuff

@Dast1Woop Hey, can you tell how can I run your fork? Like compile it into application for use

@Dast1Woop Hey, can you tell how can I run your fork? Like compile it into application for use
excute:pod install
at the root path(where you can see podfile below).
then open Knuff.xcworkspace file with Xcode  and run it(press"cmd + R" or click"Product-Run"of the menu).

Fragaria is missing


Debug Shapes

While GeometricPrimitive can draw wireframe shapes, they can be obscuring for debug purposes. A debug shape manager with a life-time based on PrimitiveBatch renderer is useful for dynamic collision and visibility testing.
XNA Game Studio Sample
Many of the debug shapes are also drawn in the DirectxMath  Collision sample.

Implemented as a helper in the wiki rather than as part of the library proper. See DebugDraw


Hi, would like to know can this library support Xcode 7.3 and Swift 2.0 ?

I did try to clone and build, but found a lot of errors, seems like incompatible code version.

I did try to clone and build, but found a lot of errors, seems like incompatible code version.

Version 5.0.1 was the final version to support Swift 2.
You would need to put this version in your pod file.
One thing though, why swift 2? :/
5.0.1 version is good, but there are many changes and bug fixes I made in version 6.0 and upwards/

I see thanks, well we are still encouraged to use the older version swift here, since the app that we build is almost completed. So we need to continue finishing them using the older swift.
Thanks for the response.

cool