Page MenuHomePhabricator

[Gadget support] Add a Javascript function to create a new portlet section similar to mw.util.addPortletLink
Closed, ResolvedPublic5 Estimated Story PointsFeature

Assigned To
Authored By
Nikki
Mar 10 2022, 1:25 AM
Referenced Files
F37133160: three menus.JPG
Jul 8 2023, 6:20 PM
Tokens
"Love" token, awarded by MusikAnimal."Like" token, awarded by Novem_Linguae."Love" token, awarded by alistair3149."Like" token, awarded by Moebeus."Like" token, awarded by So9q."Love" token, awarded by Bebiezaza."Love" token, awarded by Dinoguy1000.

Description

Feature summary (what you would like to be able to do and where):

There should be a function to create a new portlet section that can be used in scripts and gadgets, similar to how mw.util.addPortletLink can be used to add an individual link to a portlet.

Use case(s) (list the steps that you performed to discover that problem, and describe the actual underlying problem which you want to solve. Do not describe only a solution):

There are various scripts and gadgets across Wikimedia projects which create a new portlet section. They all have to generate the corresponding HTML themselves and have to be updated when the HTML for a portlet section changes, which has happened twice in the last year already.

e.g.

Benefits (why should this be implemented?):

It would be easier for script authors who wouldn't have to generate HTML themselves.
It would provide more consistency, since everyone who uses the function would get the same generated HTML.
It would mean scripts don't have to be updated whenever the HTML changes.

Background

Vector is the only WMF skin with native menu functionality. Menus are a nice way to consolidate a collection of links, as opposed to throwing them all into #p-cactions or #p-tb which can quickly become too large. mw.util.addPortletLink exists, but it only lets you add to existing portlets. If you want to create a new one, you must construct the HTML yourself. During the development of Vector-2022, this has caused repeated regressions and breakage in popular gadgets such as Twinkle and MoreMenu. It has even caused breakage in Core, namely Live Preview which also has to construct Vector HTML by hand (T262374, T303676).

There is a clear need for a JS method to create custom porlets. While there may not be a precedent for Core to support them, from which other skins can implement styling, Vector specifically seems to beg for this functionality.

T302073: [GOAL] Page Tools available on all wikis proposes even more radical changes to menus that will break gadgets, possibly in a way that is not backwards-compatible -- meaning that for gadgets used across different deployment groups, there will be a period where they are broken for some but not others. This is what happened on March 10, when gadgets maintainers waited for new HTML changes to arrive to group 2 before deploying the corresponding fixes. Although the fixes were deployed within minutes, it was still long enough to attract a flood of complaints. It would be much more ideal if we didn't have to construct the HTML ourselves and could rely on Vector to do it for us.

Proposal

Add a mw.util.addPortlet( locationId, id, label ) method, which allows to target certain parts of the UI. In Vector 2022/Vector locationId might be right-navigation (top-level menus) or mw-panel (sidebar portlets), however we should think about how this might work across skins (perhaps if the element is unavailable the JS throws an exception and the client must handle it)

Related conversation with @Jdlrobson at https://github.com/wikimedia-gadgets/MoreMenu/issues/25

@matmarex captured thoughts here: T303859#7779807

Acceptance criteria / QA steps

  • It should be possible to create an empty menu
  • It should be possible in Vector 2022 to style it as a dropdown
  • When styled as a dropdown, clicking outside the new menu should close it (see related issue in T336965)

Check the following code adds a menu to the main menu.

var x = mw.util.addPortlet('foo');
$(x).insertAfter( '#p-navigation' );


mw.util.addPortletLink('foo', '#', 'New portlet link');
mw.util.addPortletLink('foo', '#', 'New portlet link 2');

Check the following code creates a new dropdown menu

var x = mw.util.addPortlet('twinkle-2', { type: 'dropdown' } );
$(x).insertAfter( '#vector-page-tools-dropdown' );


mw.util.addPortletLink('twinkle-2', '#', 'Link inside a dropdown');

Enable the Twinkle gadget on enwiki.
Run the following code in beta cluster and confirm that the links match up with those on enwiki:

var useCactions = [ 'monobook', 'cologneblue', 'modern' ].indexOf( mw.config.get( 'skin' ) ) > -1;
var portletId = useCactions ? 'p-cactions' : 'p-twinkle';
$('#p-cactions.emptyPortlet' ).remove(); // hack not needed
if ( !$( portletId ).length ) {
    const p = mw.util.addPortlet(portletId, 'TW' );
    $( p ).insertAfter( '#p-cactions' );
}
mw.util.addPortletLink( portletId, '#', 'csd', 'tw-csd' );
mw.util.addPortletLink( portletId, '#', 'prod', 'tw-prod' );
mw.util.addPortletLink( portletId, '#', 'xfd', 'tw-xfd' );
mw.util.addPortletLink( portletId, '#', 'rpp', 'tw-rpp' );
mw.util.addPortletLink( portletId, '#', 'tag', 'tw-tag' );
mw.util.addPortletLink( portletId, '#', 'last', 'tw-last' );
mw.util.addPortletLink( portletId, '#', 'unlink', 'tw-unlink' );

Related Objects

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes

Change 928677 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/core@master] Add mw.util.addPortlet method

https://gerrit.wikimedia.org/r/928677

Jdlrobson raised the priority of this task from Medium to High.Jun 13 2023, 12:10 AM

Change 878211 restored by Jdlrobson:

[mediawiki/core@master] Allow skins to implement mediawiki.util methods

https://gerrit.wikimedia.org/r/878211

@Jdlrobson I'd like to suggest a few alternatives that might be simpler in the long-term for both skin maintenance and for frontend performance.

  1. Standardising the HTML.

As I understand it, prior to a year or two ago, the portlet HTML was actually standardised across all skins. Perhaps we we can achieve this once more, such that the HTML such that this hook isn't needed?

Historically Minerve did have its own more elaborate HTML template for menu items to support icons and labels, but this wasn't an issue in practice, because Minerva also hardcoded its own concept of page actions and sidebar items with no involvement from other extensions server-side or gadgets client-side. Thus, I wouldnt' say Minerva had "non-standard" portlet HTML, but rather it didn't have portlets. It just had a similar local concept that displayed a subset of links that other skins display via portlets.

Fast-forward several years and Minerva now leverages the core Skin system for page actions and the sidebar. It still has some overrides, but they are now on top of core rather than orthogonal to it. I vaguely remember another task from a year ago (can't find it now), where a similar issue came up. Shortly after Minerva introduced support for addPortletLink, you found that the text position and font style were different from the built-in items due to the Minerva CSS not targeting the portlet HTML as-is. If I recall correctly, this was considered too much work to support and so we instead worked around it by modifying portlets client-side after they render to add the missing class names and label wrapper element.

There were, if I recall correctly, no hard technical or design requirements preventing us from styling portlet items in Minerva pixel-identical to the way we style them today (without requiring an extra class name and wrapper element for the simple case).

  1. Offer declarative component override.

As a compromise between the hook and complete standardisation, there is one other way we could avoid the race conditions we see today, and cut out the performance costs of a runtime hook that modifies the DOM "after the fact".

Namely, we could template-ify mw.util.addPortletLink into a skin component that really just passes a key-value JSON to an HTML template string. This would be similar to the 'text-wrapper' option that you introduced but rather than special-casing one variant to the HTML, it would let the skin completely change the HTML structure for the item being created.

There's a few different ways to do this. One way to do it would be use a skin method that returns the contents of a mustache file, which subclasses can override to point to a different file.

  1. Extend the existing skin options.

Speaking of the 'text-wrapper' option. I vaguely recall an intent to remove the hook in favour of this option. It actually surprises me that Minerva and Vector22 still need the hook. I thought this option was meant to enable the core to create the portlet HTML "correctly" to the current skin needs in the first place.

I'm guessing that ended up being insufficient. However, if you a more procedural and dynamic approach over the declarative component approach, then we could probably add a few more skin options to fill in the remaining custom needs. E.g. an option to inject additional class names etc.

As I understand it, the hook would then remain for notification purposes only. i.e. Vector 22 would use it to remain notified of changes to the toolbar to copy into its sticky toolbar, the same way it already does for the initial server-rendered ones.


For the Vector 22 use case, mw.hook works exactly as you'd need I think. It ensures Vector is notified even if gadgets added portlet items before Vectors hook handler was registered, and it gets notitied only once even if multiple items were added since the last time it was notified. This is generally how we handle client-side hooks where one thing needs to respond to the current state of another.

On the other hand, for precise replaying of every item in a series of data, mw.track indeed is better suited, but that should no longer be needed if the Skin API lets the core logic render both the server-side and client-side items correctly from the start, without needing the skin to ship custom-written JS code to fix up incorrectly rendered items.

Jdlrobson set the point value for this task to 5.Jun 15 2023, 5:21 PM

Change 930882 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/skins/Vector@master] POC: Implement Vector's addPortlet method

https://gerrit.wikimedia.org/r/930882

Jdlrobson renamed this task from Add a Javascript function to create a new portlet section similar to mw.util.addPortletLink to [Gadget support] Add a Javascript function to create a new portlet section similar to mw.util.addPortletLink.Jun 20 2023, 5:09 PM

(Note another gadget broke in the absence of this API - T319358#8989256 - web team is looking to address this within the next 3 weeks)

I ended up doing this in a similar script that needed it, since that seems more reliable than depending on changing HTML structure:
https://ru.wikipedia.org/wiki/Участник:Землеройкин/remove.js#L-481

To address the concerns in T319358#8996317, we should probably give some thought to...

  • Is there a parameter we can pass in that will make these addPortlet() generated menus behave similarly to the More menu?
  • Will these More-style menus open on hover? (Right now Twinkle does, but MoreMenu does not, would be good to standardize it)
  • If one of these menus is opened, will it close all the other ones so that they do not overlap?

Will these More-style menus open on hover? (Right now Twinkle does, but MoreMenu does not, would be good to standardize it)

MoreMenu doesn't do anything as far as opening/closing the menus, rather it follows the skin behaviour. So for Vector 2022 it requires a click, but in old Vector it does not. Other skins don't have native menus so I did have to add a hover listener for those (as well as the submenus, which aren't a thing in any skin, and outside the scope of this task).

If one of these menus is opened, will it close all the other ones so that they do not overlap?

Same as above -- depends on the skin. Behind the scenes there's actually a checkbox in the Vector skins; so for old Vector you can make them "stick" open by clicking (checkbox is checked). Same is true for the native "More" menu. I.e. it's possible to have both open and this apparently was by design. In Vector-2022 however, it should close when another is clicked.

  1. should be, yes
  2. On Vector yes. On Vector 2022, no
  3. Vector no. Vector 2022 yes

Also wondering: do these gadgets officially support other skins e.g. Timeless,Modern,Monobook etc?

Also wondering: do these gadgets officially support other skins e.g. Timeless,Modern,Monobook etc?

MoreMenu does and with custom-built menus. I believe Twinkle just lists the items using mw.util.addPortletLink(). There was talk of making the MoreMenu menus into a lib that Twinkle could use, but I never got around to working on it. Once a Core mw.util.addPortlet() or the like is added, perhaps we could look into implementing menu functionality in the other skins. Not at all necessary but given it's of benefit to at least two widely used gadgets, it seems worth the volunteer time.

I was invited here from T319358: I have some more points, in case anyone here hasn't seen my gripes. And I realize this is a rapidly moving target. Using Vector-2022 on current Edge, and I don't know if I'm an an A/B test.

  1. For dropdown menus, there are two standard behaviors that I observe almost universally. The classic Win32 menu bar, where a dropdown is dismissed by click-away or hover over another menu in the bar. Or the more modern dropdown, where - and I just realized this was one contributor to my problem - the "V" hint at the availability of a dropdown is replaced by a "^" hint, which suggests another click to close, i.e. pull up, the dropdown. That visual cue is currently not provided in Page, User, or TW. It's also not provided in the shortcut menu at the top right, but that at least uses the "click away" dismissal rule.
  2. As shown in my screenshot, click User, then click Page (without dismissing User): the Page menu underlays the User menu, which is confusing. At least let the most recently clicked menu come on top. This also happens for a user with TW not enabled.
  3. On the TW click-to-close: The second click does close the menu, but because the mouse is necessarily hovering over the menu header during the click, it sort-of closes and temporary-opens at the same time. That is disconcerting also: did I click hard enough? Again, changing the hint icon between V and ^ will help answer that question, although having it remain open until I move away is still disconcerting.

Sorry about being so finicky; I'm chagrined I only just noticed this.

three menus.JPG (619×511 px, 55 KB)

Hi @Krinkle

Thank you for the input! I've summed up the Web team conversation regarding this below:

In the short term, the Web team will continue to use the approach we've been using for addPortletLink for a new method addPortlet.

The team agrees that in the long term, we want to take an approach that shares many of the goals of “Offer declarative component override.” However, we don’t want to constrain ourselves to a Mustache implementation at this point given open questions around the Vue rollout.

The web team shares the following goals regarding this work:

  1. Avoid race conditions and improve performance: Cut out the performance costs of a runtime hook that modifies the DOM "after the fact." By providing a declarative component override, the skin can demarcate the HTML structure for each item created upfront, eliminating the need for runtime modifications and potential race conditions.
  2. Flexibility and customization for skins: Skins that can change the HTML structure for each portlet item and offer greater flexibility and customization options. This solution should allow skins to control the output HTML and implement their desired UI advancements.
  3. Template agnostic: A solution that allows for easy modifications and updates to the HTML structure, agnostic to whether the skin uses templates or not (e.g., Mustache as in the case of Vector/Minerva, no templates as in Monobook, or in future Vue templates).
  4. Improved maintainability: Provide a clear structure, and a template-based system enhances maintainability. Skins should be able to rely on consistent templates and switch template languages if needed. We should be able to simplify future updates and maintenance tasks.

Regarding the other options discussed

Standardizing HTML: There are too many concerns about the practicality, maintainability, and potential limitations of formalizing the HTML for this to be a viable solution.

Extending the existing skin options: There was low support for this solution, as the HTML is significantly different across skins at this point, and this feels counter-intuitive given our template-driven approach, which. Note: We have been working towards removing the existing text-wrapper options which are too primitive to be useful.

Declarative component override: We have concerns around this relating to the transition from Mustache to Codex and how it would work for addPortlet given the addPortlet use case is far more complex than the addPortletLink (for example the dropdown HTML is very different from the tabs). We do agree that we want to avoid modifications after the element has been added to the DOM but we are not convinced the use of a key-value JSON to an HTML template string would be sufficient as the HTML would vary based on the context.

Change 939275 had a related patch set uploaded (by Mabualruz; author: Mabualruz):

[mediawiki/skins/Vector@master] Add hook support for mw.util.addPortlet method

https://gerrit.wikimedia.org/r/939275

Change 940234 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/skins/Vector@master] Test describes expected behaviour

https://gerrit.wikimedia.org/r/940234

Change 930882 abandoned by Jdlrobson:

[mediawiki/skins/Vector@master] POC: Implement Vector's addPortlet method

Reason:

Being done in https://gerrit.wikimedia.org/r/c/mediawiki/skins/Vector/+/939275 now.

https://gerrit.wikimedia.org/r/930882

Change 940234 abandoned by Jdlrobson:

[mediawiki/skins/Vector@master] Test describes expected behaviour

Reason:

https://gerrit.wikimedia.org/r/940234

Change 928677 merged by jenkins-bot:

[mediawiki/core@master] Add barebones mw.util.addPortlet method

https://gerrit.wikimedia.org/r/928677

Hey, Twinkle dev here. I see we just merged a patch that adds mw.util.addPortlet(). Awesome. I did some testing on the beta cluster, and it seems to always output the same thing no matter what skin I use.

mw.util.addPortlet('p-twinkle', 'TW')
<div class="mw-portlet mw-portlet-p-twinkle emptyPortlet mw-portlet-js" id="p-twinkle">
    <label>TW</label>
    <div>
        <ul>
            <!-- scripts can use mw.util.addPortletLink() to place items here -->
        </ul>
    </div>
</div>

Do we need some follow up patches that transform this output a bit depending on the skin? And should these patches go in core or in each skin?

For vector 2010, Twinkle.addPortlet() outputs something closer to...

<nav aria-labelledby="p-twinkle-label" class="mw-portlet vector-menu vector-menu-dropdown vector-dropdown vector-menu-dropdown-noicon" id="p-twinkle">
    <input id="p-twinkle-dropdown-checkbox" class="vector-menu-checkbox vector-dropdown-checkbox" type="checkbox" aria-labelledby="p-twinkle-label">
    <h3 id="p-twinkle-label" for="p-twinkle-dropdown-checkbox" class="vector-menu-heading vector-dropdown-label">
        <span>TW</span>
        <a href="#"></a>
    </h3>
    <div class="vector-menu-content vector-dropdown-content">
        <ul class="vector-menu-content-list">
            <!-- scripts can use mw.util.addPortletLink() to place items here -->
        </ul>
    </div>
</nav>

@Novem_Linguae Hi, yea basically we implemented a hook in vector, and adapted the hook in vector to output Vector/Vector22 complaint portlets and wrap them in appropriate wrappers and assign appropriate classes.

The aim is to have that hook utilised and adapted in each skin for it's own compatibility.

So to answer your questions

Do we need some follow up patches that transform this output a bit depending on the skin? And should these patches go in core or in each skin?

Yes, and yes for each skin and by skin maintainers.

PS: This is a new approach that we hope to be widely adopted, and improved continuously

Change 939275 merged by jenkins-bot:

[mediawiki/skins/Vector@master] Add hook support for mw.util.addPortlet method

https://gerrit.wikimedia.org/r/939275

@Novem_Linguae I'll send a more complete update later today about where we are but there are still a few moving pieces on this one!

Change 941984 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/skins/MonoBook@master] Make Monobook compatible with mw.util.addPortlet method

https://gerrit.wikimedia.org/r/941984

Change 942009 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/skins/Timeless@master] Make Timeless compatible with mw.util.addPortlet

https://gerrit.wikimedia.org/r/942009

Change 942018 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/skins/CologneBlue@master] Style portlets created with mw.util.addPortlet consistently

https://gerrit.wikimedia.org/r/942018

Change 942019 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/skins/Modern@master] Style portlets created with mw.util.addPortlet consistently

https://gerrit.wikimedia.org/r/942019

Change 942020 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/skins/Vector@master] Fix issues with addPortlet handler

https://gerrit.wikimedia.org/r/942020

I've rescoped this ticket. https://gerrit.wikimedia.org/r/942020 is the remaining blocker for passing this to QA. @Mabualruz could you take a look?

For the new API to be available to gadget maintainers, we'll need to make some minor modifications to skins. We'll do that as part of T342814. Once that's done we should have something usable to gadgets.
Twinkle in particular expects the menu to be a dropdown which is out of scope for this first particular API, but we'll be thinking through the details of that in T342815 (we have various possible approaches for dealing with that)

Thanks for your patience and interest!

Change 942020 merged by jenkins-bot:

[mediawiki/skins/Vector@master] Fix issues with addPortlet handler

https://gerrit.wikimedia.org/r/942020

Let's move QA to the follow up tickets when we have a more complete solution.

Okay, so for those following along this is not ready yet for tech news as the API still needs tweaking (see follow up tickets T342815 and T342814) , but I do invite gadget developers to try it out in the Vector 2022 skin and flag anything unexpected about it here. Please do not use the API yet for production gadgets as the API should not yet be considered stable.

As a simple user/UI tester, when can I expect a behavior change on enwiki? Still the same misbehavior on Page and User.

Per https://phabricator.wikimedia.org/T303488#9052588 there is nothing for users to test right now. Regarding the user dropdown please track T342815 for updates.

This is supposedly resolved, but it's undocumented and when I run the function, it doesn't add a portlet section anywhere that I can find.

It does appear in the code documentation (JSDuck), but it's shown as an event, not a method...

Apparently you have to attach the new portlet somewhere yourself, which is less than perfect… I don't know if that's intended or if it was overlooked.

(The portlet may also be invisible until you add some links to it.)

The following works for me:

$('#p-tb').after( mw.util.addPortlet('foo', 'Foo') );
mw.util.addPortletLink('foo', 'https://example.com', 'Example');

Please see my earlier update in T303488#9052588.

The method has not been advertised as it's not ready and/or stable.

We're currently looking for feedback/testing from gadget developers and have these two follow up tickets where your input is welcomed:

I forget which ticket I originally shared my concerns in, I think I made a post about this. But I am worried that mw.util.addPortlet() is not generating HTML that is similar enough to the skin that it is being used in. Ideally I think each skin would be able to specify what kind of addPortlet() HTML is generated, and that HTML would be identical to other HTML portlet code used by that skin.

I did some testing somewhere and discovered that there are currently big differences in the HTML generated by mw.util.addPortlet() in certain skins, and how a portlet is normally outputted in that skin.

Patches such as https://gerrit.wikimedia.org/r/c/mediawiki/skins/Timeless/+/942009/ are concerning because they are styling new HTML elements not normally used in those skins but used by the current implementation of mw.util.addPortlet(), such as .nav-block label and .nav-block .mw-portlet > div, instead of just using their native equivalents.

Is this the right approach architecturally? I feel like we shouldn't even be touching CSS.

I feel the acceptance criteria for mw.util.addPortlet() should be that it outputs identical HTML to a normal portlet in each skin.

I feel the acceptance criteria for mw.util.addPortlet() should be that it outputs identical HTML to a normal portlet in each skin.

+1 to T303488#9141334. This matches the vision I had for mw.util.addPortlet() as well. I should not only be able to add a portlet to #c-actions, but anywhere acceptable such as #mw-panel (this would be helpful to many scripts such as https://en.wikipedia.org/wiki/User:MusikAnimal/scriptManager). I think it's fine if the skin is responsible for implementing the HTML and styling. If the skin doesn't implement anything, it can throw an error or even a less-than-perfect fallback.

If we go this route, T342815 seems moot as Vector should already do this as it has for ages. Create a new portlet (before done manually, now using addPortlet()), then using addPortletLink() should turn it into a dropdown menu, assuming the portlet is in #c-actions.

T343598 I don't think needs much input. The method should act just like addPortletLink() and actually add the content, as per the method name. It's clear from the above comments that this is the expected behaviour.

If we go this route, T342815 seems moot as Vector should already do this as it has for ages.

In Vector (and Minerva), a dropdown has nothing to do with a portlet. We have dropdowns which contain things that are not portlets. A portlet component appears inside a dropdown component (due to the use of composition rather than inheritance). Historically however, in the other skins the two components are unhelpfully conflated together.

I feel the acceptance criteria for mw.util.addPortlet() should be that it outputs identical HTML to a normal portlet in each skin.

Even in legacy skins some portlets have a checkbox to make them behave as dropdowns and some do not so getting identical HTML is not going to be possible without a huge overhaul in each of these skins - and even then given skins have full control of the HTML this will be a social contract rather than a formal contract (we previously tried to use consistent markup across all skins and found it to restrict what we could do). All skins have evolved to have different capabilities which requires a different markup.

I think the current approach compromises as much as it can do - which is that it attempts to socialize a standardization of this markup. The hope is that since addPortlet always provides the same markup, this should lead to skins conforming to the markup of mw.util.addPortlet as closely as possible, as it will be easier for skins to do that and support gadgets then to use different markup.

Patches such as https://gerrit.wikimedia.org/r/c/mediawiki/skins/Timeless/+/942009/ are concerning because they are styling new HTML elements not normally used in those skins but used by the current implementation of mw.util.addPortlet(), such as .nav-block label and .nav-block .mw-portlet > div, instead of just using their native equivalents.

Right, but we have a bit of a chicken-egg sotuation here and we are going to have to start somewhere if we want to use standardized markup as you are suggesting. If we need to modify the HTML to standardize it we also need to modify the CSS :-). An obvious follow up to the Timeless patch would be to update all portlet HTML to use the label element instead of h3 for example (and then remove the h3 selectors). Isarra is technically the maintainer of this skin, so that would be her decision. I guess in the cases of Monobook, CologneBlue, Modern this is a case of patch-welcome. Minerva and Vector will likely do that once the method sees more adoption in gadgets.

T343598 I don't think needs much input.

Right I think we're all in agreement with how this should work. Just need to build that out.