@@ -82,13 +82,13 @@ follow up issue and attach it to the component implementation epic found within
...
@@ -82,13 +82,13 @@ follow up issue and attach it to the component implementation epic found within
### 4. My submit form button becomes disabled after submitting
### 4. My submit form button becomes disabled after submitting
If you are using a submit button inside a form and you attach an `onSubmit` event listener on the form element, [this piece of code](https://gitlab.com/gitlab-org/gitlab/blob/794c247a910e2759ce9b401356432a38a4535d49/app/assets/javascripts/main.js#L225)will add a `disabled` class selector to the submit button when the form is submitted.
If you are using a submit button inside a form and you attach an `onSubmit` event listener on the form element, [this piece of code](https://gitlab.com/gitlab-org/gitlab/blob/794c247a910e2759ce9b401356432a38a4535d49/app/assets/javascripts/main.js#L225)adds a `disabled` class selector to the submit button when the form is submitted.
To avoid this behavior, add the class `js-no-auto-disable` to the button.
To avoid this behavior, add the class `js-no-auto-disable` to the button.
### 5. Should I use a full URL (i.e. `gon.gitlab_url`) or a full path (i.e. `gon.relative_url_root`) when referencing backend endpoints?
### 5. Should I use a full URL (i.e. `gon.gitlab_url`) or a full path (i.e. `gon.relative_url_root`) when referencing backend endpoints?
It's preferred to use a **full path** over a **full URL** because the URL will use the hostname configured with
It's preferred to use a **full path** over a **full URL** because the URL uses the hostname configured with
GitLab which may not match the request. This will cause[CORS issues like this Web IDE one](https://gitlab.com/gitlab-org/gitlab/-/issues/36810).
GitLab which may not match the request. This causes[CORS issues like this Web IDE one](https://gitlab.com/gitlab-org/gitlab/-/issues/36810).
Example:
Example:
...
@@ -161,8 +161,9 @@ Sometimes it's necessary to test locally what the frontend production build woul
...
@@ -161,8 +161,9 @@ Sometimes it's necessary to test locally what the frontend production build woul
1. Open `gitlab.yaml` located in your `gitlab` installation folder, scroll down to the `webpack` section and change `dev_server` to `enabled: false`.
1. Open `gitlab.yaml` located in your `gitlab` installation folder, scroll down to the `webpack` section and change `dev_server` to `enabled: false`.
1. Run `yarn webpack-prod && gdk restart rails-web`.
1. Run `yarn webpack-prod && gdk restart rails-web`.
The production build takes a few minutes to be completed; any code change at this point will be
The production build takes a few minutes to be completed; any code changes at this point are
displayed only after executing the item 3 above again.
displayed only after executing the item 3 above again.
To return to the normal development mode:
To return to the normal development mode:
1. Open `gitlab.yaml` located in your `gitlab` installation folder, scroll down to the `webpack` section and change back `dev_server` to `enabled: true`.
1. Open `gitlab.yaml` located in your `gitlab` installation folder, scroll down to the `webpack` section and change back `dev_server` to `enabled: true`.
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
...
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Principles
# Principles
These principles will ensure that your frontend contribution starts off in the right direction.
These principles ensure that your frontend contribution starts off in the right direction.
## Discuss architecture before implementation
## Discuss architecture before implementation
...
@@ -14,7 +14,7 @@ Discuss your architecture design in an issue before writing code. This helps dec
...
@@ -14,7 +14,7 @@ Discuss your architecture design in an issue before writing code. This helps dec
## Be consistent
## Be consistent
There are multiple ways of writing code to accomplish the same results. We should be as consistent as possible in how we write code across our codebases. This will make it easier for us to maintain our code across GitLab.
There are multiple ways of writing code to accomplish the same results. We should be as consistent as possible in how we write code across our codebases. This makes it easier for us to maintain our code across GitLab.
@@ -12,7 +12,7 @@ easy to maintain, and performant for the end-user.
...
@@ -12,7 +12,7 @@ easy to maintain, and performant for the end-user.
## Rules
## Rules
Our CSS is a mixture of current and legacy approaches. That means sometimes it may be difficult to follow this guide to the letter; it means you will definitely run into exceptions, where following the guide is difficult to impossible without outsized effort. In those cases, you may work with your reviewers and maintainers to identify an approach that does not fit these rules. Please endeavor to limit these cases.
Our CSS is a mixture of current and legacy approaches. That means sometimes it may be difficult to follow this guide to the letter; it means you are likely to run into exceptions, where following the guide is difficult to impossible without outsized effort. In those cases, you may work with your reviewers and maintainers to identify an approach that does not fit these rules. Please endeavor to limit these cases.
### Utility Classes
### Utility Classes
...
@@ -132,8 +132,8 @@ We use [SCSS Lint](https://github.com/sds/scss-lint) to check for style guide co
...
@@ -132,8 +132,8 @@ We use [SCSS Lint](https://github.com/sds/scss-lint) to check for style guide co
ruleset in `.scss-lint.yml`, which is located in the home directory of the
ruleset in `.scss-lint.yml`, which is located in the home directory of the
project.
project.
To check if any warnings will be produced by your changes, you can run `rake
To check if any warnings are produced by your changes, run `rake
scss_lint` in the GitLab directory. SCSS Lint will also run in GitLab CI/CD to
scss_lint` in the GitLab directory. SCSS Lint also runs in GitLab CI/CD to
catch any warnings.
catch any warnings.
If the Rake task is throwing warnings you don't understand, SCSS Lint's
If the Rake task is throwing warnings you don't understand, SCSS Lint's
...
@@ -147,4 +147,4 @@ the SCSS style guide, you can use [CSSComb](https://github.com/csscomb/csscomb.j
...
@@ -147,4 +147,4 @@ the SCSS style guide, you can use [CSSComb](https://github.com/csscomb/csscomb.j
CSSComb globally (system-wide). Run it in the GitLab directory with
CSSComb globally (system-wide). Run it in the GitLab directory with
`csscomb app/assets/stylesheets` to automatically fix issues with CSS/SCSS.
`csscomb app/assets/stylesheets` to automatically fix issues with CSS/SCSS.
Note that this won't fix every problem, but it should fix a majority.
Note that this doesn't fix every problem, but it should fix a majority.
@@ -98,7 +98,7 @@ Please check this [rules](https://github.com/vuejs/eslint-plugin-vue#bulb-rules)
...
@@ -98,7 +98,7 @@ Please check this [rules](https://github.com/vuejs/eslint-plugin-vue#bulb-rules)
We discourage the use of the spread operator in this specific case in
We discourage the use of the spread operator in this specific case in
order to keep our codebase explicit, discoverable, and searchable.
order to keep our codebase explicit, discoverable, and searchable.
This applies in any place where we'll benefit from the above, such as
This applies in any place where we would benefit from the above, such as
when [initializing Vuex state](../vuex.md#why-not-just-spread-the-initial-state).
when [initializing Vuex state](../vuex.md#why-not-just-spread-the-initial-state).
The pattern above also enables us to easily parse non scalar values during
The pattern above also enables us to easily parse non scalar values during
instantiation.
instantiation.
...
@@ -667,7 +667,7 @@ The goal of this accord is to make sure we are all on the same page.
...
@@ -667,7 +667,7 @@ The goal of this accord is to make sure we are all on the same page.
1. If you need to grab data from the DOM, you may query the DOM 1 time while bootstrapping your application to grab data attributes using `dataset`. You can do this without jQuery.
1. If you need to grab data from the DOM, you may query the DOM 1 time while bootstrapping your application to grab data attributes using `dataset`. You can do this without jQuery.
1. You may use a jQuery dependency in Vue.js following [this example from the docs](https://vuejs.org/v2/examples/select2.html).
1. You may use a jQuery dependency in Vue.js following [this example from the docs](https://vuejs.org/v2/examples/select2.html).
1. If an outside jQuery Event needs to be listen to inside the Vue application, you may use jQuery event listeners.
1. If an outside jQuery Event needs to be listen to inside the Vue application, you may use jQuery event listeners.
1. We will avoid adding new jQuery events when they are not required. Instead of adding new jQuery events take a look at [different methods to do the same task](https://vuejs.org/v2/api/#vm-emit).
1. We avoid adding new jQuery events when they are not required. Instead of adding new jQuery events take a look at [different methods to do the same task](https://vuejs.org/v2/api/#vm-emit).
1. You may query the `window` object one time, while bootstrapping your application for application specific data (e.g. `scrollTo` is ok to access anytime). Do this access during the bootstrapping of your application.
1. You may query the `window` object one time, while bootstrapping your application for application specific data (e.g. `scrollTo` is ok to access anytime). Do this access during the bootstrapping of your application.
1. You may have a temporary but immediate need to create technical debt by writing code that does not follow our standards, to be refactored later. Maintainers need to be ok with the tech debt in the first place. An issue should be created for that tech debt to evaluate it further and discuss. In the coming months you should fix that tech debt, with its priority to be determined by maintainers.
1. You may have a temporary but immediate need to create technical debt by writing code that does not follow our standards, to be refactored later. Maintainers need to be ok with the tech debt in the first place. An issue should be created for that tech debt to evaluate it further and discuss. In the coming months you should fix that tech debt, with its priority to be determined by maintainers.
1. When creating tech debt you must write the tests for that code before hand and those tests may not be rewritten. e.g. jQuery tests rewritten to Vue tests.
1. When creating tech debt you must write the tests for that code before hand and those tests may not be rewritten. e.g. jQuery tests rewritten to Vue tests.
@@ -62,11 +62,11 @@ Be sure to read about [page-specific JavaScript](performance.md#page-specific-ja
...
@@ -62,11 +62,11 @@ Be sure to read about [page-specific JavaScript](performance.md#page-specific-ja
While mounting a Vue application, you might need to provide data from Rails to JavaScript.
While mounting a Vue application, you might need to provide data from Rails to JavaScript.
To do that, you can use the `data` attributes in the HTML element and query them while mounting the application.
To do that, you can use the `data` attributes in the HTML element and query them while mounting the application.
You should only do this while initializing the application, because the mounted element will be replaced with Vue-generated DOM.
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
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,
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 will make the tests easier.
which makes the tests easier.
See the following example, also, please refer to our [Vue style guide](style/vue.md#basic-rules) for additional
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;
information on why we explicitly declare the data being passed into the Vue app;
...
@@ -98,8 +98,8 @@ return new Vue({
...
@@ -98,8 +98,8 @@ return new Vue({
#### Accessing the `gl` object
#### Accessing the `gl` object
When we need to query the `gl` object for data that won't change during the application's life cycle, we should do it in the same place where we query the DOM.
When we need to query the `gl` object for data that doesn't change during the application's life cycle, we should do it in the same place where we query the DOM.
By following this practice, we can avoid the need to mock the `gl` object, which will make tests easier.
By following this practice, we can avoid the need to mock the `gl` object, which makes tests easier.
It should be done while initializing our Vue instance, and the data should be provided as `props` to the main component:
It should be done while initializing our Vue instance, and the data should be provided as `props` to the main component:
```javascript
```javascript
...
@@ -162,12 +162,12 @@ This approach has a few benefits:
...
@@ -162,12 +162,12 @@ This approach has a few benefits:
### A folder for Components
### A folder for Components
This folder holds all components that are specific of this new feature.
This folder holds all components that are specific to this new feature.
If you need to use or create a component that will probably be used somewhere
If you need to use or create a component that is likely to be used somewhere
else, please refer to `vue_shared/components`.
else, please refer to `vue_shared/components`.
A good rule of thumb to know when you should create a component is to think if
A good rule of thumb to know when you should create a component is to think if
it will be reusable elsewhere.
it could be reusable elsewhere.
For example, tables are used in a quite amount of places across GitLab, a table
For example, tables are used in a quite amount of places across GitLab, a table
would be a good fit for a component. On the other hand, a table cell used only
would be a good fit for a component. On the other hand, a table cell used only
...
@@ -192,7 +192,7 @@ Check this [page](vuex.md) for more details.
...
@@ -192,7 +192,7 @@ Check this [page](vuex.md) for more details.
In the [Vue documentation](https://vuejs.org/v2/api/#Options-Data) the Data function/object is defined as follows:
In the [Vue documentation](https://vuejs.org/v2/api/#Options-Data) the Data function/object is defined as follows:
> The data object for the Vue instance. Vue will recursively convert its properties into getter/setters to make it “reactive”. The object must be plain: native objects such as browser API objects and prototype properties are ignored. A rule of thumb is that data should just be data - it is not recommended to observe objects with their own stateful behavior.
> The data object for the Vue instance. Vue recursively converts its properties into getter/setters to make it “reactive”. The object must be plain: native objects such as browser API objects and prototype properties are ignored. A rule of thumb is that data should just be data - it is not recommended to observe objects with their own stateful behavior.
It is not recommended to replace stateful components with functional components unless you absolutely need a performance improvement right now. In Vue 3, performance gains for functional components will be negligible.
It is not recommended to replace stateful components with functional components unless you absolutely need a performance improvement right now. In Vue 3, performance gains for functional components are negligible.