mirror of
https://github.com/datahub-project/datahub.git
synced 2025-07-03 07:09:21 +00:00
fix/docs(frontend): Syncs UI with internal frontend (#2009)
* Init new and improved in repo documentation for open source and github {COMMIT-SYNC:dca335ff397c3e9c1283d845cef56fdb42f7853b} * [META-13251] Initial implementation for button to integrate with wintermute {COMMIT-SYNC:491b2bf5bc91137a2919370e81936033be15b13a} * Quickfix for UMP Datasets not showing the correct owner link {COMMIT-SYNC:26eb64cca78f96ed383994b7e67dd4fc8a99d985} * Updates history of datahub documentation {COMMIT-SYNC:306b2c72f3a81e699c8b414a8aaf4dcbfdf1ed31} Co-authored-by: Ignacio Bona <ibonapiedrabuena@linkedin.com>
This commit is contained in:
parent
1a64d6364d
commit
c739ab4f22
@ -1,4 +1,5 @@
|
|||||||
import { IOwnerResponse } from '@datahub/data-models/types/entity/dataset/ownership';
|
import { IOwnerResponse } from '@datahub/data-models/types/entity/dataset/ownership';
|
||||||
|
import { PersonEntity } from '@datahub/data-models/entity/person/person-entity';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to map legacy ownership type to new ownership type
|
* Helper method to map legacy ownership type to new ownership type
|
||||||
@ -27,7 +28,7 @@ const transformOwnerCategoryIntoType = (
|
|||||||
export const transformOwnersResponseIntoOwners = (ownersResponse: IOwnerResponse): Array<Com.Linkedin.Common.Owner> => {
|
export const transformOwnersResponseIntoOwners = (ownersResponse: IOwnerResponse): Array<Com.Linkedin.Common.Owner> => {
|
||||||
const { owners = [] } = ownersResponse;
|
const { owners = [] } = ownersResponse;
|
||||||
return owners.map(owner => ({
|
return owners.map(owner => ({
|
||||||
owner: owner.userName,
|
owner: PersonEntity.urnFromUsername(owner.userName),
|
||||||
type: transformOwnerCategoryIntoType(owner.type)
|
type: transformOwnerCategoryIntoType(owner.type)
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
@ -104,7 +104,8 @@ export default class ChangeLogContainer extends Component {
|
|||||||
* Constructs a map of userNames of each owner
|
* Constructs a map of userNames of each owner
|
||||||
*/
|
*/
|
||||||
@map('owners', function(this: ChangeLogContainer, owner: Com.Linkedin.Common.Owner): string {
|
@map('owners', function(this: ChangeLogContainer, owner: Com.Linkedin.Common.Owner): string {
|
||||||
return owner.owner;
|
const PersonEntityClass = this.dataModels.getModel(PersonEntity.displayName);
|
||||||
|
return PersonEntityClass.usernameFromUrn(owner.owner);
|
||||||
})
|
})
|
||||||
ownerUserNames!: Array<string>;
|
ownerUserNames!: Array<string>;
|
||||||
|
|
||||||
|
BIN
datahub-web/documentation/assets/os-module-diagram.png
Normal file
BIN
datahub-web/documentation/assets/os-module-diagram.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 137 KiB |
29
datahub-web/documentation/debugging/EMBER-SERVE.md
Normal file
29
datahub-web/documentation/debugging/EMBER-SERVE.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Debugging Guide for Various Errors When Trying to Run Ember Serve
|
||||||
|
======================================================================
|
||||||
|
|
||||||
|
## Node Sass Error
|
||||||
|
|
||||||
|
Sample Error:
|
||||||
|
|
||||||
|
```
|
||||||
|
Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js 13.x
|
||||||
|
|
||||||
|
Found bindings for the following environments:
|
||||||
|
- OS X 64-bit with Unsupported runtime (83)
|
||||||
|
- OS X 64-bit with Unsupported runtime (88)
|
||||||
|
|
||||||
|
This usually happens because your environment has changed since running `npm install`.
|
||||||
|
Run `npm rebuild node-sass` to download the binding for your current environment.
|
||||||
|
```
|
||||||
|
|
||||||
|
Problem:
|
||||||
|
Your version of node currently being used is not supported by node-sass. For more information on
|
||||||
|
node-sass support, check out this link: https://www.npmjs.com/package/node-sass
|
||||||
|
|
||||||
|
Solution:
|
||||||
|
Change your version of node to the correct corresponding version, and then from `datahub-web/`
|
||||||
|
run the command
|
||||||
|
|
||||||
|
```
|
||||||
|
npm rebuild
|
||||||
|
```
|
1
datahub-web/documentation/guides/EXTENDING-DATAHUB-UI.md
Normal file
1
datahub-web/documentation/guides/EXTENDING-DATAHUB-UI.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
TODO: Guide through the process of extending the repo for an internal company, similar to what we do with the @linkedin folder
|
@ -1,2 +1,177 @@
|
|||||||
TODO: Provide a history of DataHub to explain our rational for architectural choices and major decisions since the
|
A History of DataHub Frontend/UI
|
||||||
days of Wherehows and GDPR
|
==========================================================
|
||||||
|
|
||||||
|
### *Where we came from, and how we got here*
|
||||||
|
|
||||||
|
Through providing a historical context for DataHub UI, we hope to provide more insight into the decisions and
|
||||||
|
architecture behind our UI client.
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## **Before GDPR**
|
||||||
|
|
||||||
|
DataHub was originally an open source project focused on just search and discovery of datasets known as Wherehows.
|
||||||
|
During those times, our UI application would best be described as a jQuery application written inside an Ember
|
||||||
|
wrapper. Eventually, we adopted better code practices and aligned with Ember 2.x. However, there was no clear
|
||||||
|
unified thought process behind how we did things. Every feature or task was done ad hoc, and for the most part the
|
||||||
|
primary goal was to get things working.
|
||||||
|
|
||||||
|
### **Why Ember?**
|
||||||
|
|
||||||
|
We chose Ember as a framework because of its support internally at LinkedIn. A lot of libraries that we could take
|
||||||
|
advantage of were made specifically to be compatible with our internal wrapper around the Ember framework, known as
|
||||||
|
"Pemberly."
|
||||||
|
|
||||||
|
As time went on, though, we did take note that Ember is a very opinionated framework with a steep learning curve
|
||||||
|
early on. But it's for those very same reasons that the framework itself allows quick and clean iteration for code
|
||||||
|
for those who are intimately familiar with it. Additionally, as members join and leave the team internally, people
|
||||||
|
generally come in with some baseline knowledge already about Ember, which means faster ramp up time for any new
|
||||||
|
Ember application than coming into an unfamiliar React application.
|
||||||
|
|
||||||
|
Ultimately, the decision comes down to support, and we wanted to take advantage of as much as possible internally
|
||||||
|
in order to devote more time to developing new features and maintaining the existing application.
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## **GDPR Times - The Trenches**
|
||||||
|
|
||||||
|
Before we could devote a lot of time to coming up with a proper frontend architecture within the Ember ecosystem in
|
||||||
|
which we found ourselves, a rush order came. Companies around the world sought to find ways to meet GDPR compliance
|
||||||
|
and user privacy standards, and ours was no different. Internally, people realized that our application, which had
|
||||||
|
originally intended to only be a data warehouse and search tool, and its aggregation of metadata across the company was
|
||||||
|
the key to creating the backbone on which compliance efforts could be built.
|
||||||
|
|
||||||
|
And so, we got to work, the backend built to take on this new compliance pipeline and the frontend to fill in features
|
||||||
|
related to compliance tasks. Unfortunately, this rush also meant that our open source story became neglected, and tech
|
||||||
|
debt accumulated. Our UI code's maintainability was tested to the extreme... and it failed. Quick iterations are great,
|
||||||
|
but the maintainability cost in our case was too high.
|
||||||
|
|
||||||
|
### **But We Got TypeScript**
|
||||||
|
|
||||||
|
One long term benefit that arose from this period, though, was that seeing the need to increase the maintainability of
|
||||||
|
what was becoming a larger scale application internally led us to adopt TypeScript. TypeScript provides a great
|
||||||
|
avenue for maintainability in our opinion. It's not just the compilation time safety of values and variables. There was
|
||||||
|
the added benefit of editor functions like accurate autocomplete and protection against null values and undefined
|
||||||
|
objects/properties. Plus, we were able to start using classes much earlier than the point where they became widely used.
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## **Post GDPR - A New Mission**
|
||||||
|
|
||||||
|
After GDPR, our Metadata team at LinkedIn found ourselves in a new position as a team that had the most horizontal view
|
||||||
|
of all the data at LinkedIn, and that had the tools to potential solve many of the big data problems in our
|
||||||
|
organization. With this new true north in mind, we began a project called Starfleet, which effectively was meant to be
|
||||||
|
a revamp of Wherehows. Not only were we keen to solve the internal challenges, but we also wanted to revisit our open
|
||||||
|
source story and bring life back into a project that had been effectively neglected during the GDPR rush.
|
||||||
|
|
||||||
|
We found ourselves asking two questions on the UI code:
|
||||||
|
|
||||||
|
- How did we plan to be able to work with multiple teams and allow contributions from different sources?
|
||||||
|
- How did we plan to accommodate code that should exist in our internal repository and expose only what is necessary to
|
||||||
|
open source?
|
||||||
|
|
||||||
|
To solve both issues, we began looking at 2 options to do the same thing, which was to split our single Ember
|
||||||
|
into multiple modules or packages known as Ember addons. A quick introduction to what addons are can be found on the
|
||||||
|
[Ember documentation website](https://guides.emberjs.com/v3.3.0/tutorial/installing-addons/).
|
||||||
|
|
||||||
|
Each module (addon) would ultimately be consumed by our actual application. The role of the application at that point
|
||||||
|
would be to aggregate addons and ensure that the whole of the project worked properly. Each team that wanted to
|
||||||
|
collaborate with us could write an addon instead of having to learn the entire DataHub codebase, and our role on the
|
||||||
|
team would be to guide them on how to integrate with our full application at the end.
|
||||||
|
|
||||||
|
The benefit of this also extends to the open source story. How we laid out the addons was simple. There would be a
|
||||||
|
subset of modules designated as "open source" modules. These would be the components that make up DataHub UI in
|
||||||
|
the open source. Internally, we would have additional modules for two reasons:
|
||||||
|
|
||||||
|
- One, the module is an "extension" of an existing open source module that contains additional logic that would be
|
||||||
|
specific only to our internal code. Basically if the open source was our parent class, then the internal would be
|
||||||
|
a more specialized child class.
|
||||||
|
- Two, the module is an "internal only" feature or entity that should not be exposed to open source.
|
||||||
|
|
||||||
|
With the above layout and some minor tooling, we could effectively expose only said external logic to the open
|
||||||
|
source and ensure that we weren't polluting our pushes with internal business logic or features not relevant to
|
||||||
|
the open source community. A diagram that outlines this is shown below:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
### **We're a monorepo now**
|
||||||
|
|
||||||
|
Ultimately, this development led to our application becoming laid out as a mono-repository, or monorepo, using
|
||||||
|
yarn workspaces. For more information about the specifics of this, check out our documentation about our
|
||||||
|
monorepo [here](02-MONOREPO.md).
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## **Achieving More Stability**
|
||||||
|
|
||||||
|
As the development of Starfleet kicked off and we experimented for a quarter or two, there were some very valuable
|
||||||
|
lessons learned. One of the most valuable of these was that a quickly iterating team leads to a very dynamic backend.
|
||||||
|
And a very dynamic backend leads to lots of things changing and breaking on the frontend.
|
||||||
|
|
||||||
|
While developing the UI for an internal entity we wanted to onboard, metrics, we found the hard way that models, apis,
|
||||||
|
and contracts constantly change (who knew!). What we found ourselves doing, that seemed very unnecessary, though, was
|
||||||
|
constantly making massive file changes to accommodate constantly evolving interfaces. Because we called our APIs and
|
||||||
|
directly used the returned objects in our components, we made heavy assumptions on how to retrieve properties and pass
|
||||||
|
them from parent to child components or into various methods that dealt with those objects. The result was that a
|
||||||
|
single API change could unnecessarily snowball and also be prone to errors.
|
||||||
|
|
||||||
|
### **Data Models: A framework for indirection**
|
||||||
|
|
||||||
|
Our solution to the above problem was to channel the API responses through a secondary object, a JavaScript class
|
||||||
|
that defined a consistent interface. This class has knowledge of how the API behaves and contains a series of
|
||||||
|
computations and getters that expose the relevant API information in a stable way to the UI. Thus, we divided the app
|
||||||
|
into three layers: an API definition layer, a data fetching and translation layer, and a component (view) layer. If
|
||||||
|
this sounds like simply the literal definition of an MVC framework, it is. If our solution also sounds like a poor
|
||||||
|
person's GraphQL alternative solution, that's also pretty accurate.
|
||||||
|
|
||||||
|
However, Ember makes it very easy to forget these disciplines and mix concerns, and in the trenches it can be
|
||||||
|
difficult to see the greater picture. What the data models ultimately did was bring us back on track and start to
|
||||||
|
define and move toward a promised land for our UI.
|
||||||
|
|
||||||
|
For more information on our data models, read that section of our introduction [here](03-DATAMODELS.md). For more
|
||||||
|
information on where we are going with this and how we plan to move forward, check out our `forward` section of the
|
||||||
|
documentation, particularly our thoughts on adopted [GraphQL](../forward/GRAPHQL.md) and a more
|
||||||
|
[framework agnostic approach](../forward/NOFRAMEWORK.md).
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## **Rapid Growth and Quicker Onboarding**
|
||||||
|
|
||||||
|
Since the beginning of Project Starfleet our team has experienced rapid growth. Wherehows became re-branded as DataHub,
|
||||||
|
and its use internally at LinkedIn skyrocketed. We began to realize that our UI code would have difficulty scaling to
|
||||||
|
accommodate every team, feature, or entity ask that exists internally and in the open source community. One of the
|
||||||
|
goals for the UI has become allowing a quicker onboarding process for new entities, aspects, or features.
|
||||||
|
|
||||||
|
Of course, not everything can always be simply plug and play, as much as we would love that. There are many specialized
|
||||||
|
components that need to be hand made to accommodate very specific or unique use cases. However, for a large number of
|
||||||
|
cases, we can often break down the asks into basic components that share similar behaviors with other features. If we
|
||||||
|
can create a way to simply configure how those components appear on a page, and even include configurations to plug
|
||||||
|
in the more specialized components, then we could significantly improve how new asks can be onboarded for the UI.
|
||||||
|
|
||||||
|
### **And so, render props came along**
|
||||||
|
|
||||||
|
Render props are our in progress solution to the generalized UI problem, where we want to template-ize as much as
|
||||||
|
possible and allow people with little frontend knowledge to be able to modify what is essentially a JSON object to
|
||||||
|
make major modifications to the frontend UI. The idea is that, for each entity, we want to be able to hook up
|
||||||
|
behavior for how certain pages are defined and laid out, and even how they behave, based on a configuration. For
|
||||||
|
more information about how render props work on our application, check out the in-depth look
|
||||||
|
[here](04-RENDERPROPS.md).
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
## **Conclusion**
|
||||||
|
|
||||||
|
In this document, we've outlined but a few of the many challenges and learnings we've come across on our journey
|
||||||
|
so far. While many of these specific challenges are not necessarily new to the frontend world, they are more
|
||||||
|
interesting because of having to make these solutions work for a big data-centric application, which often has
|
||||||
|
much more complex and specialized use cases than a typical application.
|
||||||
|
|
||||||
|
While GMA aims to solve the generalized metadata challenge, DataHub UI aims to solve the generalized data UI
|
||||||
|
challenge associated with big metadata. For more information about our overall UI architecture, please continue
|
||||||
|
reading the rest of the `introduction`, starting [here](02-MONOREPO.md). For more information about where we plan to
|
||||||
|
take our learnings and go next, visit the `forward` section, like our thoughts on
|
||||||
|
[supporting React](../forward/REACT.md), for example.
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"rules": [
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"rules": [
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"files": [],
|
|
||||||
"rules": []
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user