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

expand orgId enrichement to other content types, and/or replace with enrichment w/ ownerUser? #543

Open
tomwayson opened this issue Jun 10, 2021 · 5 comments
Assignees

Comments

@tomwayson
Copy link
Member

Hub.js currently only fetches the orgId for a content for Hub-created web maps (we were being conservative in order to avoid making this xhr when we didn't need it).

However, now I've learned that the Hub app's content views send contentOrgId w/ telemetry. The app fetches the ownerUser for all content types and we get the id from content.ownerUser.org.id.

See: https://github.com/ArcGIS/opendata-ui/pull/9667#issuecomment-858841298 for more info.

Determine if hub app needs the whole ownerUser, or just the orgId and move that logic into fetchEnrichments.

cc @rweber-esri @juliannemarik

@tomwayson
Copy link
Member Author

tomwayson commented Jun 10, 2021

I forgot about #414, so looks like we need at least the user's name in addition to the org id, so sounds like we should update the enrichment to set ownerUser and not just orgId. We can then also set orgId (and perhaps other org properties)? later in enrichProperties.

It appears that we are fetching this for all content. I guess it should be included by default in fetchEnrichments().

@tomwayson
Copy link
Member Author

Plan:

  • replace orgId enrichment w/ a new ownerUser enrichement
  • after enrichments are fetched, call a new _processFetchedEnrichments fn instead of just _enrichDates
  • _processFetchedEnrichments will now call _enrichDates and then also have new logic for updating the content's orgId and org properties based on ownerUser

NOTE: that the current app code for fetching the owner user is here:

https://github.com/ArcGIS/opendata-ui/blob/master/packages/opendata-ui/app/services/content.js#L307-L332

That code not only fetches the user, but enriches the user object and makes a few additional requests for org info, etc. TBD how much of that needs to be done w/in enrichContent().

@dbouwman
Copy link
Member

dbouwman commented Jul 7, 2021

Enrichment Streamlining

Single entry fn

enrichContent(
  type:string,
  content:Partial<IHubContent>,
  requestOptions: IHubRequestOptions
  ):Promise<IHubContent> {...}

For composition, we should have a single input and return type for all the enrichment functions

export interface IEnrichmentOpts {
  content: Partial<IHubContent>,
  requestOptions?: IHubRequestOptions
}

Each enrichment should handle merging in any errors so we have no processing "at the end"

If there is more complex logic re: when an enrichment should be run, do that inside the enrichment vs outside... then all the logic is in one place

Each enrichment fn has this signature:

// All enrichments use promises, so we can treat them the same for composition
const enrichDates(enrichmentOpts: IEnrichmentArgs):Promise<IEnrichmentOpts> {..}

Declarative Composition:

Things to capture:

  • what should always be done
  • what should be done for specific types
  • what should be done for "summary" vs "complete"
    • basically don't super-enrich things we'll show in a list
const enrichmentMap = {
  common: {
    simple: [
      // if these are strings, we have to map into a set of functions
      // but we could also import all the fns and just list them, so
      enrichDates,
    ],
    complete: [
      enrichDates,
      ownerUser
    ]
  }
  types: {
    hubSiteApplication: {
      simple: [...],
      complete: [ domainEntries ]
    },
  }
}

Then we look up based on the type, merge common w/ any type specific stuff, and return a composition

// async pipe fn
const pipe = (...functions) => input => functions.reduce((chain, func) => chain.then(func), Promise.resolve(input));

getEnrichments(type, content) {
  const base = getWithDefault(enrichmentMap, `common.${type}`, []);
  const typeName = camelize(content.type);
  const extentions = getWithDefault(enrichmentMap, `types.${typeName}.${type}`, []);
  return [...base, ...extensions];
}

enrichContent(type: string, content:Partial<IHubContent>, ro):Promise<IHubContent> {
  const enrichments = getEnrichments(type, content);
  const opts = {content, requestOptions} as IEnrichmentOptions;
  return pipe(enrichments)(opts).then((result) => {
    return result.content;
  });

}

@dbouwman
Copy link
Member

dbouwman commented Jul 7, 2021

Discussion thoughts...

const typeName = camelize(content.type);

const typeName = getTypeName(content);

getTypeName(content: IContent): Promise<string> {
   let typeName = camelize(content.type);
   if (typeName === 'table') {
     // if url.indexOf('mapservice') {

 
     }
   }


}

const enrichmentMap = {
  common: {
    simple: [
      // if these are strings, we have to map into a set of functions
      // but we could also import all the fns and just list them, so
      enrichDates,
    ],
    complete: [
      enrichDates,
      ownerUser
    ]
  }
  types: {
    hubSiteApplication: {
      simple: [...],
      complete: [ domainEntries ]
    },
   mapServiceLayer: {
     complete: [iterateLayer]
   }
  }
}

ugly jsbin w/ rough prototype of things -> https://jsbin.com/kipafum/1/edit?html,js,console,output

@tomwayson
Copy link
Member Author

The current system allows users to pass in an arbitrary set of enrichments to (or [] to not fetch any and only do the sync enrichments of urls and dates). Basing this on enrichmentMap would require users to use predefined (named) sets of enrichments.

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

No branches or pull requests

2 participants