Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-07-24 18:10:11 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-07-24 18:10:11 +0300
commit7308ec9d13fb69018200a40f287e76ef499ed47c (patch)
tree06c75f7ddceebd61d09f925a48fef2789338f3cd /app/assets/javascripts/admin
parentf296f23500b4b3758670ae0c5ce2e1779f533e8b (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/admin')
-rw-r--r--app/assets/javascripts/admin/abuse_reports/components/abuse_report_row.vue27
-rw-r--r--app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue46
-rw-r--r--app/assets/javascripts/admin/abuse_reports/constants.js40
-rw-r--r--app/assets/javascripts/admin/abuse_reports/index.js1
-rw-r--r--app/assets/javascripts/admin/abuse_reports/utils.js18
5 files changed, 92 insertions, 40 deletions
diff --git a/app/assets/javascripts/admin/abuse_reports/components/abuse_report_row.vue b/app/assets/javascripts/admin/abuse_reports/components/abuse_report_row.vue
index b229dd9e993..291833959f2 100644
--- a/app/assets/javascripts/admin/abuse_reports/components/abuse_report_row.vue
+++ b/app/assets/javascripts/admin/abuse_reports/components/abuse_report_row.vue
@@ -14,6 +14,13 @@ export default {
ListItem,
AbuseCategory,
},
+ i18n: {
+ updatedAt: __('Updated %{timeAgo}'),
+ createdAt: __('Created %{timeAgo}'),
+ deletedUser: s__('AbuseReports|Deleted user'),
+ row: s__('AbuseReports|%{reportedUser} reported for %{category} by %{reporter}'),
+ rowWithCount: s__('AbuseReports|%{reportedUser} reported for %{category} by %{count} users'),
+ },
props: {
report: {
type: Object,
@@ -25,18 +32,24 @@ export default {
const { sort } = queryToObject(window.location.search);
const { createdAt, updatedAt } = this.report;
const { template, timeAgo } = Object.values(SORT_UPDATED_AT.sortDirection).includes(sort)
- ? { template: __('Updated %{timeAgo}'), timeAgo: updatedAt }
- : { template: __('Created %{timeAgo}'), timeAgo: createdAt };
+ ? { template: this.$options.i18n.updatedAt, timeAgo: updatedAt }
+ : { template: this.$options.i18n.createdAt, timeAgo: createdAt };
return sprintf(template, { timeAgo: getTimeago().format(timeAgo) });
},
title() {
- const { reportedUser, category, reporter } = this.report;
- const template = s__('AbuseReports|%{reportedUser} reported for %{category} by %{reporter}');
- return sprintf(template, {
- reportedUser: reportedUser?.name || s__('AbuseReports|Deleted user'),
- reporter: reporter?.name || s__('AbuseReports|Deleted user'),
+ const { reportedUser, category, reporter, count } = this.report;
+
+ const reportedUserName = reportedUser?.name || this.$options.i18n.deletedUser;
+ const reporterName = reporter?.name || this.$options.i18n.deletedUser;
+
+ const i18nRowCount = count > 1 ? this.$options.i18n.rowWithCount : this.$options.i18n.row;
+
+ return sprintf(i18nRowCount, {
+ reportedUser: reportedUserName,
+ reporter: reporterName,
category,
+ count,
});
},
},
diff --git a/app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue b/app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue
index b1eb5371a35..bab0fe6dd7d 100644
--- a/app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue
+++ b/app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue
@@ -4,43 +4,52 @@ import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_ba
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import {
FILTERED_SEARCH_TOKENS,
- DEFAULT_SORT,
- SORT_OPTIONS,
- isValidSortKey,
+ DEFAULT_SORT_STATUS_OPEN,
+ DEFAULT_SORT_STATUS_CLOSED,
} from '~/admin/abuse_reports/constants';
-import { buildFilteredSearchCategoryToken, isValidStatus } from '~/admin/abuse_reports/utils';
+
+import {
+ buildFilteredSearchCategoryToken,
+ isValidStatus,
+ isOpenStatus,
+ isValidSortKey,
+ sortOptions,
+} from '~/admin/abuse_reports/utils';
export default {
name: 'AbuseReportsFilteredSearchBar',
components: { FilteredSearchBar },
- sortOptions: SORT_OPTIONS,
inject: ['categories'],
data() {
return {
initialFilterValue: [],
- initialSortBy: DEFAULT_SORT,
+ initialSortBy: DEFAULT_SORT_STATUS_OPEN,
};
},
computed: {
tokens() {
return [...FILTERED_SEARCH_TOKENS, buildFilteredSearchCategoryToken(this.categories)];
},
+ query() {
+ return queryToObject(window.location.search);
+ },
+ currentSortOptions() {
+ return sortOptions(this.query.status);
+ },
},
created() {
- const query = queryToObject(window.location.search);
+ const { query } = this;
// Backend shows open reports by default if status param is not specified.
// To match that behavior, update the current URL to include status=open
- // query when no status query is specified on load.
+ // query when no status is specified on load.
if (!isValidStatus(query.status)) {
query.status = 'open';
updateHistory({ url: setUrlParams(query), replace: true });
}
- const sort = this.currentSortKey();
- if (sort) {
- this.initialSortBy = query.sort;
- }
+ const sortKey = this.currentSortKey();
+ this.initialSortBy = sortKey;
const tokens = this.tokens
.filter((token) => query[token.type])
@@ -56,9 +65,13 @@ export default {
},
methods: {
currentSortKey() {
- const { sort } = queryToObject(window.location.search);
+ const { status, sort } = this.query;
- return isValidSortKey(sort) ? sort : undefined;
+ if (!isValidSortKey(status, sort) || !sort) {
+ return isOpenStatus(status) ? DEFAULT_SORT_STATUS_OPEN : DEFAULT_SORT_STATUS_CLOSED;
+ }
+
+ return sort;
},
handleFilter(tokens) {
let params = tokens.reduce((accumulator, token) => {
@@ -76,6 +89,7 @@ export default {
}, {});
const sort = this.currentSortKey();
+
if (sort) {
params = { ...params, sort };
}
@@ -83,7 +97,7 @@ export default {
redirectTo(setUrlParams(params, window.location.href, true)); // eslint-disable-line import/no-deprecated
},
handleSort(sort) {
- const { page, ...query } = queryToObject(window.location.search);
+ const { page, ...query } = this.query;
redirectTo(setUrlParams({ ...query, sort }, window.location.href, true)); // eslint-disable-line import/no-deprecated
},
@@ -101,7 +115,7 @@ export default {
:search-input-placeholder="__('Filter reports')"
:initial-filter-value="initialFilterValue"
:initial-sort-by="initialSortBy"
- :sort-options="$options.sortOptions"
+ :sort-options="currentSortOptions"
data-testid="abuse-reports-filtered-search-bar"
@onFilter="handleFilter"
@onSort="handleSort"
diff --git a/app/assets/javascripts/admin/abuse_reports/constants.js b/app/assets/javascripts/admin/abuse_reports/constants.js
index acb79293dfb..8b14745543e 100644
--- a/app/assets/javascripts/admin/abuse_reports/constants.js
+++ b/app/assets/javascripts/admin/abuse_reports/constants.js
@@ -7,10 +7,9 @@ import {
} from '~/vue_shared/components/filtered_search_bar/constants';
import { s__, __ } from '~/locale';
-const STATUS_OPTIONS = [
- { value: 'closed', title: __('Closed') },
- { value: 'open', title: __('Open') },
-];
+export const STATUS_OPEN = { value: 'open', title: __('Open') };
+
+const STATUS_OPTIONS = [{ value: 'closed', title: __('Closed') }, STATUS_OPEN];
export const FILTERED_SEARCH_TOKEN_USER = {
type: 'user',
@@ -39,30 +38,39 @@ export const FILTERED_SEARCH_TOKEN_STATUS = {
operators: OPERATORS_IS,
};
-export const DEFAULT_SORT = 'created_at_desc';
-export const SORT_UPDATED_AT = Object.freeze({
+export const DEFAULT_SORT_STATUS_OPEN = 'number_of_reports_desc';
+export const DEFAULT_SORT_STATUS_CLOSED = 'created_at_desc';
+
+export const SORT_UPDATED_AT = {
id: 20,
title: __('Updated date'),
sortDirection: {
descending: 'updated_at_desc',
ascending: 'updated_at_asc',
},
-});
-const SORT_CREATED_AT = Object.freeze({
+};
+
+const SORT_CREATED_AT = {
id: 10,
title: __('Created date'),
sortDirection: {
- descending: DEFAULT_SORT,
+ descending: DEFAULT_SORT_STATUS_CLOSED,
ascending: 'created_at_asc',
},
-});
+};
+
+const SORT_NUMBER_OF_REPORTS = {
+ id: 30,
+ title: __('Number of Reports'),
+ sortDirection: {
+ descending: DEFAULT_SORT_STATUS_OPEN,
+ },
+};
-export const SORT_OPTIONS = [SORT_CREATED_AT, SORT_UPDATED_AT];
+export const SORT_OPTIONS_STATUS_CLOSED = [SORT_CREATED_AT, SORT_UPDATED_AT];
-export const isValidSortKey = (key) =>
- SORT_OPTIONS.some(
- (sort) => sort.sortDirection.ascending === key || sort.sortDirection.descending === key,
- );
+// when filtered for status=open reports, add an additional sorting option -> number of reports
+export const SORT_OPTIONS_STATUS_OPEN = [SORT_NUMBER_OF_REPORTS, ...SORT_OPTIONS_STATUS_CLOSED];
export const FILTERED_SEARCH_TOKEN_CATEGORY = {
type: 'category',
@@ -74,9 +82,9 @@ export const FILTERED_SEARCH_TOKEN_CATEGORY = {
};
export const FILTERED_SEARCH_TOKENS = [
+ FILTERED_SEARCH_TOKEN_STATUS,
FILTERED_SEARCH_TOKEN_USER,
FILTERED_SEARCH_TOKEN_REPORTER,
- FILTERED_SEARCH_TOKEN_STATUS,
];
export const ABUSE_CATEGORIES = {
diff --git a/app/assets/javascripts/admin/abuse_reports/index.js b/app/assets/javascripts/admin/abuse_reports/index.js
index dbc466af2d2..e4174e6c851 100644
--- a/app/assets/javascripts/admin/abuse_reports/index.js
+++ b/app/assets/javascripts/admin/abuse_reports/index.js
@@ -19,6 +19,7 @@ export const initAbuseReportsApp = () => {
return new Vue({
el,
+ name: 'AbuseReportsAppRoot',
provide: { categories },
render: (createElement) =>
createElement(AbuseReportsApp, {
diff --git a/app/assets/javascripts/admin/abuse_reports/utils.js b/app/assets/javascripts/admin/abuse_reports/utils.js
index d30e8fb0ae5..a3d05e4dcb3 100644
--- a/app/assets/javascripts/admin/abuse_reports/utils.js
+++ b/app/assets/javascripts/admin/abuse_reports/utils.js
@@ -1,4 +1,10 @@
-import { FILTERED_SEARCH_TOKEN_CATEGORY, FILTERED_SEARCH_TOKEN_STATUS } from './constants';
+import {
+ FILTERED_SEARCH_TOKEN_CATEGORY,
+ FILTERED_SEARCH_TOKEN_STATUS,
+ STATUS_OPEN,
+ SORT_OPTIONS_STATUS_OPEN,
+ SORT_OPTIONS_STATUS_CLOSED,
+} from './constants';
export const buildFilteredSearchCategoryToken = (categories) => {
const options = categories.map((c) => ({ value: c, title: c }));
@@ -7,3 +13,13 @@ export const buildFilteredSearchCategoryToken = (categories) => {
export const isValidStatus = (status) =>
FILTERED_SEARCH_TOKEN_STATUS.options.map((o) => o.value).includes(status);
+
+export const isOpenStatus = (status) => status === STATUS_OPEN.value;
+
+export const sortOptions = (status) =>
+ isOpenStatus(status) ? SORT_OPTIONS_STATUS_OPEN : SORT_OPTIONS_STATUS_CLOSED;
+
+export const isValidSortKey = (status, key) =>
+ sortOptions(status).some(
+ (sort) => sort.sortDirection.ascending === key || sort.sortDirection.descending === key,
+ );