Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add new enterprise settings tab Connected Apps #11937

Merged
merged 10 commits into from
Dec 18, 2023

Conversation

mkllnk
Copy link
Member

@mkllnk mkllnk commented Dec 14, 2023

What? Why?

Screencast.from.2023-12-15.16-31-13.webm

What should we test?

Testing requirement: the last step of testing needs the n8n workflow:

  • n8n workflow finished

Production test only

I realised that the n8n workflows are all tied to the Australian production server and therefore we can't test it in staging. We may change that but for now, we can just merge this. It's feature-toggled.

Testing steps:

  • Activate feature connected_apps for user, enterprise or instance.
  • Visit enterprise settings.
  • Select tab Connected apps
  • Click on Share data.
  • Maybe observe a loading message.
  • Then observe a notice to finish the setup.
  • Press on that button and see a form containing your enterprise details.

Release notes

Changelog Category (reviewers may add a label for the release notes):

  • User facing changes
  • API changes (V0, V1, DFC or Webhook)
  • Technical changes only
  • Feature toggled

The title of the pull request will be included in the release notes.

Dependencies

This depends on a certain n8n workflow. The webhook URL is hardcoded.

Documentation updates

@mkllnk mkllnk added the technical changes only These pull requests do not contain user facing changes and are grouped in release notes label Dec 14, 2023
@mkllnk mkllnk self-assigned this Dec 14, 2023
@mkllnk mkllnk force-pushed the dfc-app branch 2 times, most recently from a815014 to 702e93e Compare December 14, 2023 22:19
I would have like to use a standard form to submit to the reflex but the
whole enterprise settings tab is in a form already and HTML doesn't
allow nested forms. While it does still work in browsers, it would have
added much more HTML to set up a form with a hidden input field instead
of just one additional data attribute.

The whole page is rendered by the controller again but the reflex root
attribute ensures that only parts of this tab are replaced. Otherwise
unsaved data on other tabs could be replaced and the page actually
becomes blank because AngularJS doesn't play well with the morph.
@mkllnk mkllnk marked this pull request as ready for review December 15, 2023 01:39
# frozen_string_literal: true

module Admin
class ConnectedAppReflex < ApplicationReflex
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The StimulusReflex documentation mentions that singular and plural naming of reflexes is allowed and the choice depends on the circumstances. We use both in OFN. The plural seems to be useful when the reflex is listing or searching for collections, e.g. many orders. I decided to keep it simple and go with the singular. But over time, we may realise that any reflex could be expanded to deal with collections as well and then the plural would be better. To avoid renaming, we may introduce a convention but I don't see enough of a pattern yet.

@@ -1,11 +1,17 @@
%div
%div{ data: {reflex: {root: ".connected-app__head, .connected-app__connection"}} }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reflex root will be replaced later.

it "stores connection data on the app" do
subject.perform_now

expect(app.data).to eq({ "link" => "https://example.net/edit" })
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The URL will change on the live endpoint once it's implemented. We may not be able to do live recordings then because we don't want to add our test enterprise to the live database. Maybe we can have a test mode, let's see.


return unless channel

selector = "#edit_enterprise_#{enterprise.id} #connected_apps_panel div"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have multiple tabs open with other enterprises then you don't want to show this enterprise's information on another enterprise's page.

Comment on lines +16 to +17
# Avoid race condition by sending before enqueuing job:
cable_ready.morph(selector:, html:).broadcast
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change on the page is almost instant now. Previously, it was calling the edit action of the enterprises controller and there was a noticeable lag. That action renders lots of data, including a select box with all enterprises of the platform and all kind of options for every tab of the enterprise settings. In contrast, the partial is very small.

Copy link
Member

@dacook dacook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great implementation, well done!

It looks good too. The only thing is it would be good to use some CSS variables, which should help with the long-term maintenance of the stylesheet.

Comment on lines +4 to +5
%h3= t ".title"
%p= t ".tagline"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this bracket-less format, I can't believe we weren't doing this before!
Now if only we could make lazy-lookup the default, and go back to symbols it would be beautiful 💎

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add our own helper:

# I18n lazy translate
def lt(key, *args)
  I18n.t(".#{key}", *args)
end

What do you think? Saves one character, I suppose:

= lt :tagline

And it wouldn't be well known. Not worth it.

margin-bottom: 1em;

h3 {
margin-bottom: 1em;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to think we already have reasonable margins for h3 and p by default, but I guess not.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have thought so, too. But they must be overridden somewhere. Maybe it will be better in the new design?

subject.save!
subject.reload

expect(subject.data).to eq({ "link" => "https://example.net" })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I wonder if Rails has a way for it to be with_indifferent_access by default and therefore load the hash with symbol keys.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would need to add a few things:
https://gist.github.com/RobinDaugherty/5e7bc2a6e2369a29c77c

Or we just override a method on the model:

def data
  data.try(:with_indifferent_access)
end

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at this and we currently have only one single line of access to this data:

enterprise.connected_apps[0].data&.fetch("link", false)

And in this scenario it would only change "link" to :link which isn't making a real difference. I'll leave this.

Comment on lines 20 to 21
border-left: 4px solid #008397;
border-radius: 4px;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we'd use a variable for the colour. $color-3 is spree-blue in the old design, and the new teal in the new design.
Also, we can use a variable for border-radius. This helps ensure the left border is the same width as the radius.

Suggested change
border-left: 4px solid #008397;
border-radius: 4px;
border-left: $border-radius solid $color-3;
border-radius: $border-radius;

This will look a bit different on the old design, but I think should be ok.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There could also be a variable for box-shadow, but I have a PR in progress for that, so let's just leave it hardcoded here for now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good to know. So $color-3 is available in the old and new design? I guess, once the new design is released, we can do a simple search/replace.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is much better!
Screenshot from 2023-12-15 16-22-15
Screenshot from 2023-12-15 16-22-32

access_token: token,
}

response = WebhookDeliveryJob.perform_now(url, event, payload)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay, nice to see the WebhookDeliveryJob in use!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed this is a wrapper for WebhookDeliveryJob. Would it make sense to subclass it I wonder? I can't think it would make much difference..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In doubt, I tend to avoid inheritance. This job could be seen as a special webhook job which also captures the response. But it's also doing UX stuff and it may expand one day. Only part of it is the webhook functionality. So I think that composition is the better pattern here.

Copy link
Member

@dacook dacook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops that was meant to be a 'request changes' for the CSS variables.

@mkllnk mkllnk requested a review from dacook December 15, 2023 05:28
Copy link
Member

@dacook dacook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I have to admit I accidentally missed the last two commits before.
But it all looks fine 👍

@mariocarabotta mariocarabotta added pr-staged-au staging.openfoodnetwork.org.au and removed pr-staged-au staging.openfoodnetwork.org.au labels Dec 17, 2023
Copy link
Collaborator

@rioug rioug left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one, I like your use of a reflex.


module Admin
class ConnectedAppReflex < ApplicationReflex
def create
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's tested in a system spec, but I wonder if we should also have unit test for reflexes ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I find unit tests good for testing individual methods with all the different code branches. But this method doesn't actually have any branching. And that means that the system spec is providing 100% code coverage. So I wouldn't bother at this point.

Actually, I overlooked one thing. The authorize! call is a code branch. We could test permissions in a unit test. Same for find and create! which could raise errors. But that's well-known behaviour we deal with all the time.

@mkllnk mkllnk merged commit b52b0c0 into openfoodfoundation:master Dec 18, 2023
56 checks passed
@mkllnk mkllnk deleted the dfc-app branch December 18, 2023 02:37
@mkllnk mkllnk removed the pr-staged-au staging.openfoodnetwork.org.au label Dec 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
technical changes only These pull requests do not contain user facing changes and are grouped in release notes
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Enterprise User controls data sharing
4 participants