diff --git a/.markdownlint.yml b/.markdownlint.yml
index ccf2ef02eee..35e8ef119be 100644
--- a/.markdownlint.yml
+++ b/.markdownlint.yml
@@ -1,3 +1,4 @@
+---
# Base Markdownlint configuration
# Extended Markdownlint configuration in doc/.markdownlint/
"default": true
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 32b7211cb61..7d47e599800 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.40.0
+1.41.0
diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js
index b671d038ce8..f45af5fe08e 100644
--- a/app/assets/javascripts/activities.js
+++ b/app/assets/javascripts/activities.js
@@ -42,7 +42,7 @@ export default class Activities {
}
updateTooltips() {
- localTimeAgo($('.js-timeago', '.content_list'));
+ localTimeAgo(document.querySelectorAll('.content_list .js-timeago'));
}
reloadActivities() {
diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js
index da7fc88d8ac..39dc4a4e9e5 100644
--- a/app/assets/javascripts/commits.js
+++ b/app/assets/javascripts/commits.js
@@ -93,7 +93,7 @@ export default class CommitsList {
.text(n__('%d commit', '%d commits', commitsCount));
}
- localTimeAgo($processedData.find('.js-timeago'));
+ localTimeAgo($processedData.find('.js-timeago').get());
return processedData;
}
diff --git a/app/assets/javascripts/lib/utils/datetime/timeago_utility.js b/app/assets/javascripts/lib/utils/datetime/timeago_utility.js
index 0199cf20ace..5c6c5ccd5c1 100644
--- a/app/assets/javascripts/lib/utils/datetime/timeago_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime/timeago_utility.js
@@ -1,4 +1,3 @@
-import $ from 'jquery';
import * as timeago from 'timeago.js';
import { languageCode, s__, createDateTimeFormat } from '../../../locale';
import { formatDate } from './date_format_utility';
@@ -97,21 +96,21 @@ export const getTimeago = () =>
/**
* For the given elements, sets a tooltip with a formatted date.
- * @param {JQuery} $timeagoEls
- * @param {Boolean} setTimeago
+ * @param {Array|NodeList} elements
+ * @param {Boolean} updateTooltip
*/
-export const localTimeAgo = ($timeagoEls, setTimeago = true) => {
+export const localTimeAgo = (elements, updateTooltip = true) => {
const { format } = getTimeago();
- $timeagoEls.each((i, el) => {
- $(el).text(format($(el).attr('datetime'), timeagoLanguageCode));
+ elements.forEach((el) => {
+ el.innerText = format(el.dateTime, timeagoLanguageCode);
});
- if (!setTimeago) {
+ if (!updateTooltip) {
return;
}
function addTimeAgoTooltip() {
- $timeagoEls.each((i, el) => {
+ elements.forEach((el) => {
// Recreate with custom template
el.setAttribute('title', formatDate(el.dateTime));
});
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 63c25136f74..88ddd12594e 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -183,7 +183,7 @@ document.addEventListener('DOMContentLoaded', () => {
return true;
});
- localTimeAgo($('abbr.timeago, .js-timeago'), true);
+ localTimeAgo(document.querySelectorAll('abbr.timeago, .js-timeago'), true);
/**
* This disables form buttons while a form is submitting
diff --git a/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
index 1e9f79927ea..0c20f935d50 100644
--- a/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
+++ b/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
@@ -38,6 +38,7 @@ export default {
usersName: user.name,
source: source.fullName,
},
+ false,
);
}
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index c3c3aacae35..1d1c0a23fab 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -333,8 +333,9 @@ export default class MergeRequestTabs {
axios
.get(`${source}.json`)
.then(({ data }) => {
- document.querySelector('div#commits').innerHTML = data.html;
- localTimeAgo($('.js-timeago', 'div#commits'));
+ const commitsDiv = document.querySelector('div#commits');
+ commitsDiv.innerHTML = data.html;
+ localTimeAgo(commitsDiv.querySelectorAll('.js-timeago'));
this.commitsLoaded = true;
this.scrollToContainerElement('#commits');
@@ -407,7 +408,7 @@ export default class MergeRequestTabs {
initChangesDropdown(this.stickyTop);
- localTimeAgo($('.js-timeago', 'div#diffs'));
+ localTimeAgo(document.querySelectorAll('#diffs .js-timeago'));
syntaxHighlight($('#diffs .js-syntax-highlight'));
if (this.isDiffAction(this.currentAction)) {
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index cd44e8b4987..ef51587734d 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -358,7 +358,7 @@ export default class Notes {
setupNewNote($note) {
// Update datetime format on the recent note
- localTimeAgo($note.find('.js-timeago'), false);
+ localTimeAgo($note.find('.js-timeago').get(), false);
this.collapseLongCommitList();
this.taskList.init();
@@ -511,7 +511,7 @@ export default class Notes {
Notes.animateAppendNote(noteEntity.html, discussionContainer);
}
- localTimeAgo($('.js-timeago'), false);
+ localTimeAgo(document.querySelectorAll('.js-timeago'), false);
Notes.checkMergeRequestStatus();
return this.updateNotesCount(1);
}
diff --git a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
index a3b78da6ef5..413163c8536 100644
--- a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
+++ b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
@@ -58,7 +58,7 @@ export default {
},
computed: {
modalTitle() {
- return sprintf(this.title, { username: this.username });
+ return sprintf(this.title, { username: this.username }, false);
},
secondaryButtonLabel() {
return s__('AdminUsers|Block user');
@@ -112,7 +112,7 @@ export default {
-
+
diff --git a/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js b/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js
index 8d152ec4ba6..d61209f904d 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare.js
@@ -15,7 +15,7 @@ const updateCommitList = (url, $loadingIndicator, $commitList, params) => {
.then(({ data }) => {
$loadingIndicator.hide();
$commitList.html(data);
- localTimeAgo($('.js-timeago', $commitList));
+ localTimeAgo($commitList.get(0).querySelectorAll('.js-timeago'));
});
};
diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js
index f9d70845560..90eafa85886 100644
--- a/app/assets/javascripts/pages/users/user_tabs.js
+++ b/app/assets/javascripts/pages/users/user_tabs.js
@@ -166,7 +166,7 @@ export default class UserTabs {
const tabSelector = `div#${action}`;
this.$parentEl.find(tabSelector).html(data.html);
this.loaded[action] = true;
- localTimeAgo($('.js-timeago', tabSelector));
+ localTimeAgo(document.querySelectorAll(`${tabSelector} .js-timeago`));
this.toggleLoading(false);
})
@@ -209,7 +209,7 @@ export default class UserTabs {
container,
url: $(`${container} .overview-content-list`).data('href'),
...options,
- postRenderCallback: () => localTimeAgo($('.js-timeago', container)),
+ postRenderCallback: () => localTimeAgo(document.querySelectorAll(`${container} .js-timeago`)),
});
}
diff --git a/app/assets/javascripts/vue_shared/components/oncall_schedules_list.vue b/app/assets/javascripts/vue_shared/components/oncall_schedules_list.vue
index ff2847624c5..e37a663ace3 100644
--- a/app/assets/javascripts/vue_shared/components/oncall_schedules_list.vue
+++ b/app/assets/javascripts/vue_shared/components/oncall_schedules_list.vue
@@ -27,9 +27,13 @@ export default {
title() {
return this.isCurrentUser
? s__('OnCallSchedules|You are currently a part of:')
- : sprintf(s__('OnCallSchedules|User %{name} is currently part of:'), {
- name: this.userName,
- });
+ : sprintf(
+ s__('OnCallSchedules|User %{name} is currently part of:'),
+ {
+ name: this.userName,
+ },
+ false,
+ );
},
footer() {
return this.isCurrentUser
diff --git a/danger/datateam/Dangerfile b/danger/datateam/Dangerfile
index 0a33cb6777b..e054cddce06 100644
--- a/danger/datateam/Dangerfile
+++ b/danger/datateam/Dangerfile
@@ -1,14 +1,24 @@
# frozen_string_literal: true
# rubocop:disable Style/SignalException
+DATA_WAREHOUSE_LABELS = [
+ "Data Warehouse::Impact Check",
+ "Data Warehouse::Impacted",
+ "Data Warehouse::Not Impacted"
+].freeze
+
CHANGED_SCHEMA_MESSAGE = <<~MSG
-Mentioning @gitlab-data/engineers to notify the team about changes to the db/structure.sql file.
+Notification to the Data Team about changes to the db/structure.sql file, add label `Data Warehouse::Impact Check`.
+
+/label ~"Data Warehouse::Impact Check"
MSG
db_schema_updated = !git.modified_files.grep(%r{\Adb/structure\.sql}).empty?
-if db_schema_updated
+no_data_warehouse_labels = (gitlab.mr_labels & DATA_WAREHOUSE_LABELS).empty?
+
+if db_schema_updated && no_data_warehouse_labels
markdown(CHANGED_SCHEMA_MESSAGE)
diff --git a/doc/.markdownlint/markdownlint-no-trailing-spaces.yml b/doc/.markdownlint/markdownlint-no-trailing-spaces.yml
index 3d107a3e667..71903ae423d 100644
--- a/doc/.markdownlint/markdownlint-no-trailing-spaces.yml
+++ b/doc/.markdownlint/markdownlint-no-trailing-spaces.yml
@@ -1,3 +1,4 @@
+---
# Extended Markdown configuration to enforce no-trailing-spaces rule
"extends": "../../.markdownlint.yml"
"no-trailing-spaces": true
diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml
index 2077cdf9994..bc8f38fe5e2 100644
--- a/doc/.vale/gitlab/Acronyms.yml
+++ b/doc/.vale/gitlab/Acronyms.yml
@@ -120,6 +120,7 @@ exceptions:
- PUT
- RAID
- RAM
+ - RBAC
- RDP
- REST
- RFC
diff --git a/doc/.vale/gitlab/HeaderGerunds.yml b/doc/.vale/gitlab/HeaderGerunds.yml
index c73ed78da34..9e5fa19f867 100644
--- a/doc/.vale/gitlab/HeaderGerunds.yml
+++ b/doc/.vale/gitlab/HeaderGerunds.yml
@@ -1,5 +1,5 @@
---
-# Error: gitlab.HeaderGerunds
+# Suggestion: gitlab.HeaderGerunds
#
# Checks for headers that start with gerunds (ing words).
# Related to: https://docs.gitlab.com/ee/development/documentation/structure.html
diff --git a/doc/administration/auth/authentiq.md b/doc/administration/auth/authentiq.md
index 2eab4555c85..835293ff500 100644
--- a/doc/administration/auth/authentiq.md
+++ b/doc/administration/auth/authentiq.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
To enable the Authentiq OmniAuth provider for passwordless authentication you must register an application with Authentiq.
-Authentiq will generate a Client ID and the accompanying Client Secret for you to use.
+Authentiq generates a Client ID and the accompanying Client Secret for you to use.
1. Get your Client credentials (Client ID and Client Secret) at [Authentiq](https://www.authentiq.com/developers).
@@ -67,15 +67,17 @@ Authentiq will generate a Client ID and the accompanying Client Secret for you t
1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
-On the sign in page there should now be an Authentiq icon below the regular sign in form. Click the icon to begin the authentication process.
+On the sign in page there should now be an Authentiq icon below the regular sign in form. Click the
+icon to begin the authentication process. If the user:
-- If the user has the Authentiq ID app installed in their iOS or Android device, they can:
+- Has the Authentiq ID app installed in their iOS or Android device, they can:
1. Scan the QR code.
1. Decide what personal details to share.
1. Sign in to your GitLab installation.
-- If not they will be prompted to download the app and then follow the procedure above.
+- Does not have the app installed, they are prompted to download the app and then follow the
+ procedure above.
-If everything goes right, the user will be returned to GitLab and will be signed in.
+If everything works, the user is returned to GitLab and is signed in.