Redirect to page after purchase

AI-generated summary

The discussion revolves around redirecting users to a specific page after a purchase in the Discourse subscriptions plugin. pfaffman explains they’ve implemented a solution using add_model_callback to create a server after a purchase and want to redirect to the server’s configuration page post-purchase. They initially tried using window.location in Ember, but the issue is a race condition where the server list is stale when queried. merefield suggests using DiscourseURL.routeTo after a closeModal action. pfaffman found the relevant code in the subscriptions plugin and modified the _advanceSuccessfulTransaction method to redirect using transitionToRoute, but still faces the stale data issue. They note the solution works when the server exists before purchase, but fails when the server is created during the purchase process due to timing issues.

I have add_model_callback(DiscourseSubscriptions::Customer, :after_save) do ... in a plugin. Most purchases result in a “server” (a custom model) being created. Today, I’ve managed to learn how to make other places where a server gets created transition to the page to configure the new server, with something like

      Server.createServer(server).then((result) => {
        if (result.server) {
          this.get("servers").pushObject(EmberObject.create(result.server));
          const id = result.server.id;
          window.location = getURL(`/pfaffmanager/servers/${id}`);
        }

What I’d like to do now is have Discourse similarly redirect to that new page after the “thanks for your purchase” dialog has been dismissed.

I don’t care whether it happens in Rails or Ember, but I guess it needs to happen in Ember? I don’t quite understand (that is, I have no idea, whatsoever) how to hijack extend the controller/model/whatever in the subscriptions plugin from my plugin.

There’s probably an action closeModal (maybe in the route).

Within that you could perform DiscourseURL.routeTo("/yourdiscourseroute");

Well, not quite. But, miraculously, that was enough! I found this:

And then I did this!!

      api.modifyClass("controller:subscribe-show", {
        pluginId: "pfaffmanager",
        async _advanceSuccessfulTransaction(plan) {
          window.console.log("modifying subscription!!!", plan, this);
          this.alert("plans.success");
          this.set("loading", false);
          let servers = [];
          servers = await Server.listServers().then((result) => {
            if (currentUser && currentUser.servers !== undefined) {
              servers = currentUser.servers.sort((b, a) => {
                return ("" + a.updated_at).localeCompare(b.updated_at);
              });
              window.console.log("sorted servers", servers);
              if (servers.length > 0) {
                window.console.log(`going to first! ${servers[0].id}`);
                this.transitionToRoute(
                  "pfaffmanager.servers.show",
                  servers[0].id
                );
              } else {
                window.console.log(`server not found. going to index!`);
                this.transitionToRoute("pfaffmanager.servers.index");
              }
              // window.location = getURL(`/`);
              // window.location = getURL(`/pfaffmanager/servers/${id}`);
            }
          });
        },
      });

Which is so very, fary, close. The issue now is that there is a race condition, as the add_model_callback(DiscourseSubscriptions::Customer, :after_save) do might not be finished before I do my ajax query to get the servers.

Well, it’s stranger than that. Even if I add a delay (using later) before it does the ajax call to get the new server list, it is still getting a stale list, not the one after the new server has been added in the callback. I can refresh the window in another tab and see that it gets the right data before it does the ajax call.

I guess I’ll give up for now. For the case whether the server exists before the purchase (which I think is more common–you’d configure everything and then say, “yeah, let’s do it”) it works; it’s just the case where they say “Yeah, I want to pay for an installation; I’ll pay and then see what happens.”