diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-19 12:08:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-19 12:08:42 +0300 |
commit | b76ae638462ab0f673e5915986070518dd3f9ad3 (patch) | |
tree | bdab0533383b52873be0ec0eb4d3c66598ff8b91 /doc/development/fe_guide | |
parent | 434373eabe7b4be9593d18a585fb763f1e5f1a6f (diff) |
Add latest changes from gitlab-org/gitlab@14-2-stable-eev14.2.0-rc42
Diffstat (limited to 'doc/development/fe_guide')
-rw-r--r-- | doc/development/fe_guide/dependencies.md | 47 | ||||
-rw-r--r-- | doc/development/fe_guide/design_anti_patterns.md | 11 | ||||
-rw-r--r-- | doc/development/fe_guide/design_patterns.md | 3 | ||||
-rw-r--r-- | doc/development/fe_guide/graphql.md | 2 | ||||
-rw-r--r-- | doc/development/fe_guide/haml.md | 74 | ||||
-rw-r--r-- | doc/development/fe_guide/index.md | 8 | ||||
-rw-r--r-- | doc/development/fe_guide/performance.md | 6 | ||||
-rw-r--r-- | doc/development/fe_guide/style/scss.md | 3 | ||||
-rw-r--r-- | doc/development/fe_guide/troubleshooting.md | 2 | ||||
-rw-r--r-- | doc/development/fe_guide/vue.md | 69 |
10 files changed, 165 insertions, 60 deletions
diff --git a/doc/development/fe_guide/dependencies.md b/doc/development/fe_guide/dependencies.md index e8e251baafc..c4f30fd36c9 100644 --- a/doc/development/fe_guide/dependencies.md +++ b/doc/development/fe_guide/dependencies.md @@ -24,52 +24,7 @@ production assets post-compile. ## Updating dependencies -We use the [Renovate GitLab Bot](https://gitlab.com/gitlab-org/frontend/renovate-gitlab-bot) to -automatically create merge requests for updating dependencies of several projects. -You can find the up-to-date list of projects managed by the renovate bot in the project's README. - -Some key dependencies updated using renovate are: - -- [`@gitlab/ui`](https://gitlab.com/gitlab-org/gitlab-ui) -- [`@gitlab/svgs`](https://gitlab.com/gitlab-org/gitlab-svgs) -- [`@gitlab/eslint-plugin`](https://gitlab.com/gitlab-org/frontend/eslint-plugin) -- And any other package in the `@gitlab/` scope - -We have the goal of updating [_all_ dependencies with renovate](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/21). - -Updating dependencies automatically has several benefits, have a look at this [example MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53613). - -- MRs will be created automatically when new versions are released -- MRs can easily be rebased and updated with just checking a checkbox in the MR description -- MRs contain changelog summaries and links to compare the different package versions -- MRs can be assigned to people directly responsible for the dependencies - -### Community contributions updating dependencies - -It is okay to reject Community Contributions that solely bump dependencies. -Simple dependency updates are better done automatically for the reasons provided above. -If a community contribution needs to be rebased, runs into conflicts, or goes stale, the effort required -to instruct the contributor to correct it often outweighs the benefits. - -If a dependency update is accompanied with significant migration efforts, due to major version updates, -a community contribution is acceptable. - -Here is a message you can use to explain to community contributors as to why we reject simple updates: - -```markdown -Hello CONTRIBUTOR! - -Thank you very much for this contribution. It seems like you are doing a "simple" dependency update. - -If a dependency update is as simple as increasing the version number, we'd like a Bot to do this to save you and ourselves some time. - -This has certain benefits as outlined in our <a href="https://docs.gitlab.com/ee/development/fe_guide/dependencies.html#updating-dependencies">Frontend development guidelines</a>. - -You might find that we do not currently update DEPENDENCY automatically, but we are planning to do so in [the near future](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/21). - -Thank you for understanding, I will close this Merge Request. -/close -``` +See the main [Dependencies](../dependencies.md) page for general information about dependency updates. ### Blocked dependencies diff --git a/doc/development/fe_guide/design_anti_patterns.md b/doc/development/fe_guide/design_anti_patterns.md index 0788921fce4..9e602b1ea04 100644 --- a/doc/development/fe_guide/design_anti_patterns.md +++ b/doc/development/fe_guide/design_anti_patterns.md @@ -12,7 +12,8 @@ generally be avoided. Throughout the GitLab codebase, there may be historic uses of these anti-patterns. Please [use discretion](https://about.gitlab.com/handbook/engineering/#balance-refactoring-and-velocity) when figuring out whether or not to refactor, when touching code that uses one of these legacy patterns. -**Please note:** For new features, anti-patterns are not necessarily prohibited, but it is **strongly suggested** to find another approach. +NOTE: +For new features, anti-patterns are not necessarily prohibited, but it is **strongly suggested** to find another approach. ## Shared Global Object (Anti-pattern) @@ -59,7 +60,7 @@ Shared Global Object's solve the problem of making something globally accessible could be appropriate: - When a responsibility is truly global and should be referenced across the application - (e.g., an application-wide Event Bus). + (for example, an application-wide Event Bus). Even in these scenarios, please consider avoiding the Shared Global Object pattern because the side-effects can be notoriously difficult to reason with. @@ -136,8 +137,8 @@ many problems with a module that exports utility functions. Singletons solve the problem of enforcing there to be only 1 instance of a thing. It's possible that a Singleton could be appropriate in the following rare cases: -- We need to manage some resource that **MUST** have just 1 instance (i.e. some hardware restriction). -- There is a real [cross-cutting concern](https://en.wikipedia.org/wiki/Cross-cutting_concern) (e.g., logging) and a Singleton provides the simplest API. +- We need to manage some resource that **MUST** have just 1 instance (that is, some hardware restriction). +- There is a real [cross-cutting concern](https://en.wikipedia.org/wiki/Cross-cutting_concern) (for example, logging) and a Singleton provides the simplest API. Even in these scenarios, please consider avoiding the Singleton pattern. @@ -174,7 +175,7 @@ export const fuzzify = (id) => { /* ... */ }; #### Dependency Injection [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) is an approach which breaks -coupling by declaring a module's dependencies to be injected from outside the module (e.g., through constructor parameters, a bona-fide Dependency Injection framework, and even Vue's `provide/inject`). +coupling by declaring a module's dependencies to be injected from outside the module (for example, through constructor parameters, a bona-fide Dependency Injection framework, and even Vue's `provide/inject`). ```javascript // bad - Vue component coupled to Singleton diff --git a/doc/development/fe_guide/design_patterns.md b/doc/development/fe_guide/design_patterns.md index c769d0767e7..03575f7e7f9 100644 --- a/doc/development/fe_guide/design_patterns.md +++ b/doc/development/fe_guide/design_patterns.md @@ -9,7 +9,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w The following design patterns are suggested approaches for solving common problems. Use discretion when evaluating if a certain pattern makes sense in your situation. Just because it is a pattern, doesn't mean it is a good one for your problem. -**Please note:** When adding a design pattern to this document, be sure to clearly state the **problem it solves**. +NOTE: +When adding a design pattern to this document, be sure to clearly state the **problem it solves**. ## TBD diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md index 7fa9e957f56..3b49601f027 100644 --- a/doc/development/fe_guide/graphql.md +++ b/doc/development/fe_guide/graphql.md @@ -110,7 +110,7 @@ Default client accepts two parameters: `resolvers` and `config`. If you are make multiple queries to the same Apollo client object you might encounter the following error: "Store error: the application attempted to write an object with no provided ID but the store already contains an ID of SomeEntity". [This error only should occur when you have made a query with an ID field for a portion, then made another that returns what would be the same object, but is missing the ID field.](https://github.com/apollographql/apollo-client/issues/2510#issue-271829009) -Please note this is being tracked in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/326101) and the documentation will be updated when this issue is resolved. +This is being tracked in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/326101) and the documentation will be updated when this issue is resolved. ## GraphQL Queries diff --git a/doc/development/fe_guide/haml.md b/doc/development/fe_guide/haml.md new file mode 100644 index 00000000000..8f501007755 --- /dev/null +++ b/doc/development/fe_guide/haml.md @@ -0,0 +1,74 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# HAML + +[HAML](https://haml.info/) is the [Ruby on Rails](https://rubyonrails.org/) template language that GitLab uses. + +## GitLab UI form builder + +[GitLab UI](https://gitlab-org.gitlab.io/gitlab-ui/) is a Vue component library that conforms +to the [Pajamas design system](https://design.gitlab.com/). Most of these components +rely on JavaScript and therefore can only be used in Vue. + +However, some of the simpler components (checkboxes, radio buttons, form inputs) can be +used in HAML by applying the correct CSS classes to the elements. A custom +[Ruby on Rails form builder](https://gitlab.com/gitlab-org/gitlab/-/blob/7c108df101e86d8a27d69df2b5b1ff1fc24133c5/lib/gitlab/form_builders/gitlab_ui_form_builder.rb) exists to help use GitLab UI components in HAML. + +### Use the GitLab UI form builder + +To use the GitLab UI form builder: + +1. Change `form_for` to `gitlab_ui_form_for`. +1. Change `f.check_box` to `f.gitlab_ui_checkbox_component`. +1. Remove `f.label` and instead pass the label as the second argument in `f.gitlab_ui_checkbox_component`. + +For example: + +- Before: + + ```haml + = form_for @group do |f| + .form-group.gl-mb-3 + .gl-form-checkbox.custom-control.custom-checkbox + = f.check_box :prevent_sharing_groups_outside_hierarchy, disabled: !can_change_prevent_sharing_groups_outside_hierarchy?(@group), class: 'custom-control-input' + = f.label :prevent_sharing_groups_outside_hierarchy, class: 'custom-control-label' do + %span + = s_('GroupSettings|Prevent members from sending invitations to groups outside of %{group} and its subgroups.').html_safe % { group: link_to_group(@group) } + %p.help-text= prevent_sharing_groups_outside_hierarchy_help_text(@group) + ``` + +- After: + + ```haml + = gitlab_ui_form_for @group do |f| + .form-group.gl-mb-3 + = f.gitlab_ui_checkbox_component :prevent_sharing_groups_outside_hierarchy, + s_('GroupSettings|Prevent members from sending invitations to groups outside of %{group} and its subgroups.').html_safe % { group: link_to_group(@group) }, + help_text: prevent_sharing_groups_outside_hierarchy_help_text(@group), + checkbox_options: { disabled: !can_change_prevent_sharing_groups_outside_hierarchy?(@group) } + ``` + +### Available components + +When using the GitLab UI form builder, the following components are available for use in HAML. + +NOTE: +Currently only `gitlab_ui_checkbox_component` is available but more components are planned. + +#### gitlab_ui_checkbox_component + +[GitLab UI Docs](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-form-form-checkbox--default) + +| Argument | Description | Type | Required (default value) | +|---|---|---|---| +| `method` | Attribute on the object passed to `gitlab_ui_form_for`. | `Symbol` | `true` | +| `label` | Checkbox label. | `String` | `true` | +| `help_text` | Help text displayed below the checkbox. | `String` | `false` (`nil`) | +| `checkbox_options` | Options that are passed to [Rails `check_box` method](https://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-check_box). | `Hash` | `false` (`{}`) | +| `checked_value` | Value when checkbox is checked. | `String` | `false` (`'1'`) | +| `unchecked_value` | Value when checkbox is unchecked. | `String` | `false` (`'0'`) | +| `label_options` | Options that are passed to [Rails `label` method](https://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-label). | `Hash` | `false` (`{}`) | diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md index 325310ad05c..549fa3261b1 100644 --- a/doc/development/fe_guide/index.md +++ b/doc/development/fe_guide/index.md @@ -12,9 +12,13 @@ across the GitLab frontend team. ## Overview GitLab is built on top of [Ruby on Rails](https://rubyonrails.org). It uses [Haml](https://haml.info/) and a JavaScript-based frontend with [Vue.js](https://vuejs.org). + <!-- vale gitlab.Spelling = NO --> + Be wary of [the limitations that come with using Hamlit](https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md#limitations). + <!-- vale gitlab.Spelling = YES --> + We also use [SCSS](https://sass-lang.com) and plain JavaScript with modern ECMAScript standards supported through [Babel](https://babeljs.io/) and ES module support through [webpack](https://webpack.js.org/). @@ -81,6 +85,10 @@ Vue specific [design patterns and practices](vue.md). How to use [GraphQL](graphql.md). +## HAML + +How to use [HAML](haml.md). + ## Icons and Illustrations How we use SVG for our [Icons and Illustrations](icons.md). diff --git a/doc/development/fe_guide/performance.md b/doc/development/fe_guide/performance.md index e7f347554d7..94beecf6168 100644 --- a/doc/development/fe_guide/performance.md +++ b/doc/development/fe_guide/performance.md @@ -212,6 +212,8 @@ When writing code for real-time features we have to keep a couple of things in m Thus, we must strike a balance between sending requests and the feeling of real-time. Use the following rules when creating real-time solutions. +<!-- vale gitlab.Spelling = NO --> + 1. The server tells you how much to poll by sending `Poll-Interval` in the header. Use that as your polling interval. This enables system administrators to change the [polling rate](../../administration/polling.md). @@ -219,11 +221,13 @@ Use the following rules when creating real-time solutions. 1. A response with HTTP status different from 2XX should disable polling as well. 1. Use a common library for polling. 1. Poll on active tabs only. Please use [Visibility](https://github.com/ai/visibilityjs). -1. Use regular polling intervals, do not use <!-- vale gitlab.Spelling = NO --> backoff polling <!-- vale gitlab.Spelling = YES --> or jitter, as the interval is +1. Use regular polling intervals, do not use backoff polling or jitter, as the interval is controlled by the server. 1. The backend code is likely to be using ETags. You do not and should not check for status `304 Not Modified`. The browser transforms it for you. +<!-- vale gitlab.Spelling = YES --> + ### Lazy Loading Images To improve the time to first render we are using lazy loading for images. This works by setting diff --git a/doc/development/fe_guide/style/scss.md b/doc/development/fe_guide/style/scss.md index 4a9446f2949..6d9bbdd3f2d 100644 --- a/doc/development/fe_guide/style/scss.md +++ b/doc/development/fe_guide/style/scss.md @@ -21,8 +21,11 @@ In order to reduce the generation of more CSS as our site grows, prefer the use #### Where are utility classes defined? Prefer the use of [utility classes defined in GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/main/doc/css.md#utilities). + <!-- vale gitlab.Spelling = NO --> + An easy list of classes can also be [seen on Unpkg](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss). + <!-- vale gitlab.Spelling = YES --> Classes in [`utilities.scss`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/stylesheets/utilities.scss) and [`common.scss`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/stylesheets/framework/common.scss) are being deprecated. diff --git a/doc/development/fe_guide/troubleshooting.md b/doc/development/fe_guide/troubleshooting.md index 028184e0397..14943cca3ac 100644 --- a/doc/development/fe_guide/troubleshooting.md +++ b/doc/development/fe_guide/troubleshooting.md @@ -38,7 +38,7 @@ See [this video](https://youtu.be/-BkEhghP-kM) for an in-depth overview and inve + expect(wrapper.findComponent(ChildComponent).props()).toMatchObject(...); ``` -Please note that `toMatchObject` actually changes the nature of the assertion and won't fail if some items are **missing** from the expectation. +`toMatchObject` actually changes the nature of the assertion and won't fail if some items are **missing** from the expectation. ### Script issues diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md index 0a769f257d0..509e2f4b688 100644 --- a/doc/development/fe_guide/vue.md +++ b/doc/development/fe_guide/vue.md @@ -66,12 +66,68 @@ To do that, you can use the `data` attributes in the HTML element and query them You should only do this while initializing the application, because the mounted element is replaced with a Vue-generated DOM. -The advantage of providing data from the DOM to the Vue instance through `props` in the `render` -function instead of querying the DOM inside the main Vue component is avoiding the need to create a -fixture or an HTML element in the unit test, which makes the tests easier. +The advantage of providing data from the DOM to the Vue instance through `props` or +`provide` in the `render` function, instead of querying the DOM inside the main Vue +component, is that you avoid the need to create a fixture or an HTML element in the unit test. -See the following example. Also, please refer to our [Vue style guide](style/vue.md#basic-rules) for -additional information on why we explicitly declare the data being passed into the Vue app; +##### provide/inject + +Vue supports dependency injection through [provide/inject](https://vuejs.org/v2/api/#provide-inject). +Values passed to the component through `provide` can be accessed in the component the `inject` configuration. +In the following example of a Vue app initialization, a value from HAML is passed to the component +through the `provide` configuration: + +```javascript +#js-vue-app{ data: { endpoint: 'foo' }} + +// index.js +const el = document.getElementById('js-vue-app'); + +if (!el) return false; + +const { endpoint } = el.dataset; + +return new Vue({ + el, + render(createElement) { + return createElement('my-component', { + provide: { + endpoint + }, + }); + }, +}); +``` + +The component, or any of its child components, can access the property through `inject` as: + +```vue +<script> + export default { + name: 'MyComponent', + inject: ['endpoint'], + ... + ... + }; +</script> +<template> + ... + ... +</template> +``` + +Using dependency injection to provide values from HAML is ideal when: + +- The injected value doesn't need an explicit validation against its data type or contents. +- The value doesn't need to be reactive. +- There are multiple components in the hierarchy that need access to this value where + prop-drilling becomes an inconvenience. Prop-drilling when the same prop is passed + through all components in the hierarchy until the component that is genuinely using it. + +##### props + +If the value from HAML doesn't fit the criteria of dependency injection, use `props`. +See the following example. ```javascript // haml @@ -99,6 +155,9 @@ return new Vue({ > When adding an `id` attribute to mount a Vue application, please make sure this `id` is unique across the codebase. +For more information on why we explicitly declare the data being passed into the Vue app, +refer to our [Vue style guide](style/vue.md#basic-rules). + #### Providing Rails form fields to Vue applications When composing a form with Rails, the `name`, `id`, and `value` attributes of form inputs are generated |