Skip to content

Conversation

@larkin
Copy link
Contributor

@larkin larkin commented Jul 5, 2017

This is a discussion / develop branch for finalizing the view API.

  • renamed openmct.mainViews to openmct.objectViews. I think this is more clear that these are views of an object, and separates them from "indicators" and the soon-to-be "inspector view".
  • Updated view provider to allow metadata definitions and to play nicely with old style views.
  • Roughed in some updates to ViewProviders and ViewRegistry to support further use of views.

For testing, you can define a view by adding the following to index.html:

openmct.objectViews.addProvider({
    name: 'my view',
    canView: function (d) {
        return d.type === 'folder' && 150;
    },
    view: function (domainObject) {
        return {
            show: function (container) {
                container.innerHTML = '<div> Congratulations, this is a view of: ' + domainObject.name + '</div>';
            },
            destroy: function (container) {

            }
        }
    }
});

@VWoeltjen et all, feedback appreciated. (@luisschubert you may also be interested).

@larkin
Copy link
Contributor Author

larkin commented Aug 3, 2017

TODO: Need to handle editable / separate views for edit mode.

@larkin
Copy link
Contributor Author

larkin commented Aug 3, 2017

TODO: need to address container sizing. If someone wants to inject a view that is 100% of the width and height of the container, they need to intentionally add the "abs" class to the container. Either we document this as a thing view developers need to do, or we add this class to the container so they don't have to worry about it.

@adoubekk adoubekk mentioned this pull request Aug 8, 2017
4 tasks
@VWoeltjen
Copy link
Contributor

TODO: need to address container sizing. If someone wants to inject a view that is 100% of the width and height of the container, they need to intentionally add the "abs" class to the container. Either we document this as a thing view developers need to do, or we add this class to the container so they don't have to worry about it.

I think we should add this class at a container level from the platform whenever that layout behavior is desired. Simpler, meets principle of least surprise (I do not expect to need to worry about the layouts of container elements when I'm writing a view plugin), reduces our effective API surface (insofar as CSS classes are "APIs") and gives us more implementation flexibility in the future.

@VWoeltjen
Copy link
Contributor

TODO: Need to handle editable / separate views for edit mode.

Running through some options:

  1. We've talked about using context objects for selections; this is another case where context information would be useful.
  2. editors could be a wholly separate extension point. That looks really good in the view-as-object world (don't show the Edit button if there are no editors registered). With a many-to-one view-to-object relationship, we'd need keys or something to pair editors to their appropriate views.
  3. Editing could be handled in the same view instance by listening for events (e.g. changes between browse and edit modes). In some sense this is the simplest solution, but using events to track application state presents an easy opportunity for things to fall out of sync.

I'm leaning toward Option 2 given current status. Feels clean and straightforward. The many-to-one problem makes it a little difficult, but view-as-object should entirely mitigate that.

@akhenry
Copy link
Contributor

akhenry commented Oct 19, 2017

@VWoeltjen I like editors as a separate extension point. It makes it super clear to developers how to add a new editing view of an object. It also doesn't actually stop you from using the same view if you want to, you could just check on view initialization whether the object is currently being edited, which avoids the need to listen to event changes.

@VWoeltjen VWoeltjen requested review from VWoeltjen and removed request for VWoeltjen October 19, 2017 21:57
Copy link
Contributor

@akhenry akhenry left a comment

Choose a reason for hiding this comment

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

Looks good. Excited to start using the new view API! A couple of comments inline.

// be defaults by returning priority less than 100.
};
if (v.provider) {
vd.priority = v.provider.canView(newDomainObject);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not so sure about canView returning priority. It's kind of nice in that you can treat anything non-zero as boolean true if you don't care about its priority, but it will inevitably lead to type checking in client code.

Also it doesn't seem obvious to me that it's going to return priority, and it feels like it's violating the "Do One Thing" rule.

Separating out priority will complicate the view provider interface, but will improve clarity I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

per discussion:

  • canview returns boolean
  • priority function is optional, when present takes object and returns priority (number)

* @name objectViews
*/
this.mainViews = new ViewRegistry();
this.objectViews = new ViewRegistry();
Copy link
Contributor

Choose a reason for hiding this comment

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

Noice

* views.
* @private
*/
ViewRegistry.prototype._getByVPID = function (vpid) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I've been tempted in the past to use the _ prefix, but decided against it in lieu of better JSDocs. Since we're potentially moving our API docs away from JSDoc this might be a good convention to use, so long as we use it consistently. The danger is that anything not prefixed with an _ is considered fair game by developers. Eg. .get() is also marked private but doesn't have an underscore.

* @returns {boolean} true if this domain object can be viewed using
* this provider
* @returns {Number|boolean} if this returns `false`, then the view does
* not apply to the object. If it returns true or any number, then
Copy link
Contributor

Choose a reason for hiding this comment

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

See above comments about canView vs priority.

* @memberof module:openmct.ViewRegistry#
*/
ViewRegistry.prototype.addProvider = function (provider) {
provider._vpid = this._next_id++;
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe view providers should just have keys? Or is the vpid just internal wiring for compatibility with legacy views? My jetlag addled brain is having trouble understanding vpid

Copy link
Contributor Author

Choose a reason for hiding this comment

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

per discussion, yes view providers should have keys.

@akhenry
Copy link
Contributor

akhenry commented Oct 20, 2017

Pushed two commits. The first separates out priority and canView. Not sure priority is being used properly at the moment in the new view API, openmct.objectViews.get() should probably return a list of views sorted by priority, no?

The second commit replaces vpid with a view provider key.

Need to do some testing and sanity-checking tomorrow to ensure that what I've committed is not the lunatic ravings of a jetlagged mind, and is at least up to the standard of my usual drivel.

Also, still need to fix those code style errors.

@akhenry akhenry requested a review from VWoeltjen October 20, 2017 17:36
@akhenry
Copy link
Contributor

akhenry commented Oct 20, 2017

@larkin I'm done with this if you want to take a look.

@VWoeltjen Since this impacts your work on the heatmap view I'm assigning you reviewer :)

@dtailor90 This also affects summary widgets and rover view as view providers now require a 'key' and canView should no longer return priority. If priority is required, a separate priority function can be implemented. A notional view with a low priority defined would look like:

openmct.objectViews.addProvider({
    key: 'my-view',
    name: 'my view',
    canView: function (d) {
        return d.type === 'folder';
    },
    priority: function (d) {
        return 1000;
    },
    view: function (domainObject) {
        return {
            show: function (container) {
                container.innerHTML = '<div> Congratulations, this is a view of: ' + domainObject.name + '</div>';
            },
            destroy: function (container) {

            }
        }
    }
});

akhenry
akhenry previously approved these changes Oct 20, 2017
src/MCT.js Outdated

this.objectViews.getAllProviders().forEach(function (p) {
this.legacyExtension('views', {
key: 'provider-namespace-' + p.key,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

per discussion: don't prefix

throw "View providers must have a unique 'key' defined";
}
if (this.providers[key] !== undefined) {
throw "Provider already defined for key '" + key + "'. Keys must be unique.";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

per discussion; make this a warning at most, allow overrides.

@larkin
Copy link
Contributor Author

larkin commented Oct 20, 2017

Writing this post so I can link a few developers to it. Can also integrate into API docs later.

changes for existing users

For anyone currently using the view API, the following changes need to be made to your usage of the view API after this pull request (#1642) is merged:

  • openmct.mainViews.addProvider(provider) is now openmct.objectViews.addProvider(provider)
  • providers must have a key property, a unique identifier for this view provider.
  • provider.canView must return a boolean.

For a more complete listing of supported properties, look no further than this handy dandy table.

Object View Provider properties

property type description
key string required a unique identifier for this view provider.
canView function required is called with a single argument, domainObject and should return true if the view provider can provider a view for the given domainObject.
view function required is called with a single argument, domainObject, and must return a view instance.
priority function optional is called with a single argument, domainObject, and should return a priority (a number) for the given domain Object. Small values (e.g. 1) are higher priority than large values (e.g. 1000).
editable boolean optional defaults to false. If false, attempting to edit this view will display the edit properties dialog. If true, the edit action will trigger edit mode, allowing your view to implement specialized editing behavior within Open MCT's editor sandbox (allowing changes to be made, and then saved or discarded).
name string optional a human-readable name for your view, displayed when there is more than one possible view for an object.
cssClass string optional display class for your view label, typically used to show an icon when there is more than one possible view for an object.
description string optional a human-readable description of your view, displayed when there is more than one possible view for an object.

@akhenry
Copy link
Contributor

akhenry commented Oct 20, 2017

I've squished all the commits for this branch into one.

@larkin
Copy link
Contributor Author

larkin commented Oct 21, 2017

Leaving an author checklist as a partial author, @akhenry can post review and author checklists as the other partial author.

Author Checklist

  1. Changes address original issue? Y (as described here)
  2. Unit tests included and/or updated with changes? (N/A, none exist)
  3. Command line build passes? Y
  4. Changes have been smoke-tested? Y

@akhenry
Copy link
Contributor

akhenry commented Oct 21, 2017

Author Checklist

  • Changes address original issue? Y
  • Unit tests included and/or updated with changes? N/A
  • Command line build passes? Y
  • Changes have been smoke-tested? Y

@akhenry akhenry requested review from akhenry and removed request for VWoeltjen October 21, 2017 00:10
@larkin
Copy link
Contributor Author

larkin commented Oct 21, 2017

Reviewer Checklist (For Andrew's authorship)

  1. Changes appear to address issue? Y
  2. Appropriate unit tests included? N/A
  3. Code style and in-line documentation are appropriate? Y
  4. Commit messages meet standards? Y

Copy link
Contributor

@akhenry akhenry left a comment

Choose a reason for hiding this comment

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

Reviewer Checklist

  • Changes appear to address issue? Y
  • Appropriate unit tests included? N/A
  • Code style and in-line documentation are appropriate? Y
  • Commit messages meet standards? Y

@larkin larkin merged commit 7f68d26 into master Oct 21, 2017
@akhenry akhenry deleted the view-api-implementation branch October 21, 2017 00:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants