summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/groups
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-12-17 11:59:07 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-12-17 11:59:07 +0000
commit8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca (patch)
tree544930fb309b30317ae9797a9683768705d664c4 /app/assets/javascripts/groups
parent4b1de649d0168371549608993deac953eb692019 (diff)
downloadgitlab-ce-8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca.tar.gz
Add latest changes from gitlab-org/gitlab@13-7-stable-eev13.7.0-rc42
Diffstat (limited to 'app/assets/javascripts/groups')
-rw-r--r--app/assets/javascripts/groups/components/group_folder.vue2
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue30
-rw-r--r--app/assets/javascripts/groups/components/visibility_level_dropdown.vue48
-rw-r--r--app/assets/javascripts/groups/index.js3
-rw-r--r--app/assets/javascripts/groups/members/components/app.vue10
-rw-r--r--app/assets/javascripts/groups/members/index.js21
-rw-r--r--app/assets/javascripts/groups/members/utils.js5
-rw-r--r--app/assets/javascripts/groups/store/groups_store.js5
-rw-r--r--app/assets/javascripts/groups/store/utils.js27
-rw-r--r--app/assets/javascripts/groups/visibility_level.js24
10 files changed, 159 insertions, 16 deletions
diff --git a/app/assets/javascripts/groups/components/group_folder.vue b/app/assets/javascripts/groups/components/group_folder.vue
index d2a613bed4f..5f169832ee4 100644
--- a/app/assets/javascripts/groups/components/group_folder.vue
+++ b/app/assets/javascripts/groups/components/group_folder.vue
@@ -49,7 +49,7 @@ export default {
/>
<li v-if="hasMoreChildren" class="group-row">
<a :href="parentGroup.relativePath" class="group-row-contents has-more-items py-2">
- <gl-icon name="external-link" aria-hidden="true" /> {{ moreChildrenStats }}
+ <gl-icon name="external-link" /> {{ moreChildrenStats }}
</a>
</li>
</ul>
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index 6e99b6ad4fa..ef58b93c049 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -74,6 +74,9 @@ export default {
visibilityTooltip() {
return GROUP_VISIBILITY_TYPE[this.group.visibility];
},
+ microdata() {
+ return this.group.microdata || {};
+ },
},
mounted() {
if (this.group.name === 'Learn GitLab') {
@@ -99,7 +102,15 @@ export default {
</script>
<template>
- <li :id="groupDomId" :class="rowClass" class="group-row" @click.stop="onClickRowGroup">
+ <li
+ :id="groupDomId"
+ :class="rowClass"
+ class="group-row"
+ :itemprop="microdata.itemprop"
+ :itemtype="microdata.itemtype"
+ :itemscope="microdata.itemscope"
+ @click.stop="onClickRowGroup"
+ >
<div
:class="{ 'project-row-contents': !isGroup }"
class="group-row-contents d-flex align-items-center py-2 pr-3"
@@ -118,7 +129,13 @@ export default {
class="avatar-container rect-avatar s32 d-none flex-grow-0 flex-shrink-0 "
>
<a :href="group.relativePath" class="no-expand">
- <img v-if="hasAvatar" :src="group.avatarUrl" class="avatar s40" />
+ <img
+ v-if="hasAvatar"
+ :src="group.avatarUrl"
+ data-testid="group-avatar"
+ class="avatar s40"
+ :itemprop="microdata.imageItemprop"
+ />
<identicon v-else :entity-id="group.id" :entity-name="group.name" size-class="s40" />
</a>
</div>
@@ -127,9 +144,11 @@ export default {
<div class="d-flex align-items-center flex-wrap title namespace-title gl-mr-3">
<a
v-gl-tooltip.bottom
+ data-testid="group-name"
:href="group.relativePath"
:title="group.fullName"
class="no-expand gl-mt-3 gl-mr-3 gl-text-gray-900!"
+ :itemprop="microdata.nameItemprop"
>{{
// ending bracket must be by closing tag to prevent
// link hover text-decoration from over-extending
@@ -146,7 +165,12 @@ export default {
</span>
</div>
<div v-if="group.description" class="description">
- <span v-html="group.description"> </span>
+ <span
+ :itemprop="microdata.descriptionItemprop"
+ data-testid="group-description"
+ v-html="group.description"
+ >
+ </span>
</div>
</div>
<div v-if="isGroupPendingRemoval">
diff --git a/app/assets/javascripts/groups/components/visibility_level_dropdown.vue b/app/assets/javascripts/groups/components/visibility_level_dropdown.vue
new file mode 100644
index 00000000000..ff0f8c3ff46
--- /dev/null
+++ b/app/assets/javascripts/groups/components/visibility_level_dropdown.vue
@@ -0,0 +1,48 @@
+<script>
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ },
+ props: {
+ visibilityLevelOptions: {
+ type: Array,
+ required: true,
+ },
+ defaultLevel: {
+ type: Number,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ selectedOption: this.getDefaultOption(),
+ };
+ },
+ methods: {
+ getDefaultOption() {
+ return this.visibilityLevelOptions.find(option => option.level === this.defaultLevel);
+ },
+ onClick(option) {
+ this.selectedOption = option;
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <input type="hidden" name="group[visibility_level]" :value="selectedOption.level" />
+ <gl-dropdown :text="selectedOption.label" class="gl-w-full" menu-class="gl-w-full! gl-mb-0">
+ <gl-dropdown-item
+ v-for="option in visibilityLevelOptions"
+ :key="option.level"
+ :secondary-text="option.description"
+ @click="onClick(option)"
+ >
+ <div class="gl-font-weight-bold gl-mb-1">{{ option.label }}</div>
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+</template>
diff --git a/app/assets/javascripts/groups/index.js b/app/assets/javascripts/groups/index.js
index 522f1d16df2..e11c3aaf984 100644
--- a/app/assets/javascripts/groups/index.js
+++ b/app/assets/javascripts/groups/index.js
@@ -47,8 +47,9 @@ export default (containerId = 'js-groups-tree', endpoint, action = '') => {
data() {
const { dataset } = dataEl || this.$options.el;
const hideProjects = parseBoolean(dataset.hideProjects);
+ const showSchemaMarkup = parseBoolean(dataset.showSchemaMarkup);
const service = new GroupsService(endpoint || dataset.endpoint);
- const store = new GroupsStore(hideProjects);
+ const store = new GroupsStore({ hideProjects, showSchemaMarkup });
return {
action,
diff --git a/app/assets/javascripts/groups/members/components/app.vue b/app/assets/javascripts/groups/members/components/app.vue
index 2e6dd4a0bad..f6f3a955813 100644
--- a/app/assets/javascripts/groups/members/components/app.vue
+++ b/app/assets/javascripts/groups/members/components/app.vue
@@ -1,13 +1,16 @@
<script>
import { mapState, mapMutations } from 'vuex';
import { GlAlert } from '@gitlab/ui';
-import MembersTable from '~/vue_shared/components/members/table/members_table.vue';
+import MembersTable from '~/members/components/table/members_table.vue';
+import FilterSortContainer from '~/members/components/filter_sort/filter_sort_container.vue';
import { scrollToElement } from '~/lib/utils/common_utils';
-import { HIDE_ERROR } from '~/vuex_shared/modules/members/mutation_types';
+import { HIDE_ERROR } from '~/members/store/mutation_types';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'GroupMembersApp',
- components: { MembersTable, GlAlert },
+ components: { MembersTable, FilterSortContainer, GlAlert },
+ mixins: [glFeatureFlagsMixin()],
computed: {
...mapState(['showError', 'errorMessage']),
},
@@ -33,6 +36,7 @@ export default {
<gl-alert v-if="showError" ref="errorAlert" variant="danger" @dismiss="hideError">{{
errorMessage
}}</gl-alert>
+ <filter-sort-container v-if="glFeatures.groupMembersFilteredSearch" />
<members-table />
</div>
</template>
diff --git a/app/assets/javascripts/groups/members/index.js b/app/assets/javascripts/groups/members/index.js
index cb28fb057c9..9ce0e3c1179 100644
--- a/app/assets/javascripts/groups/members/index.js
+++ b/app/assets/javascripts/groups/members/index.js
@@ -3,9 +3,18 @@ import Vuex from 'vuex';
import { GlToast } from '@gitlab/ui';
import { parseDataAttributes } from 'ee_else_ce/groups/members/utils';
import App from './components/app.vue';
-import membersModule from '~/vuex_shared/modules/members';
+import membersStore from '~/members/store';
-export const initGroupMembersApp = (el, tableFields, tableAttrs, requestFormatter) => {
+export const initGroupMembersApp = (
+ el,
+ {
+ tableFields = [],
+ tableAttrs = {},
+ tableSortableFields = [],
+ requestFormatter = () => {},
+ filteredSearchBar = { show: false },
+ },
+) => {
if (!el) {
return () => {};
}
@@ -13,15 +22,17 @@ export const initGroupMembersApp = (el, tableFields, tableAttrs, requestFormatte
Vue.use(Vuex);
Vue.use(GlToast);
- const store = new Vuex.Store({
- ...membersModule({
+ const store = new Vuex.Store(
+ membersStore({
...parseDataAttributes(el),
currentUserId: gon.current_user_id || null,
tableFields,
tableAttrs,
+ tableSortableFields,
requestFormatter,
+ filteredSearchBar,
}),
- });
+ );
return new Vue({
el,
diff --git a/app/assets/javascripts/groups/members/utils.js b/app/assets/javascripts/groups/members/utils.js
index 662eecc4e38..2d584556bbc 100644
--- a/app/assets/javascripts/groups/members/utils.js
+++ b/app/assets/javascripts/groups/members/utils.js
@@ -1,5 +1,5 @@
import { isUndefined } from 'lodash';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { convertObjectPropsToCamelCase, parseBoolean } from '~/lib/utils/common_utils';
import {
GROUP_MEMBER_BASE_PROPERTY_NAME,
GROUP_MEMBER_ACCESS_LEVEL_PROPERTY_NAME,
@@ -8,12 +8,13 @@ import {
} from './constants';
export const parseDataAttributes = el => {
- const { members, groupId, memberPath } = el.dataset;
+ const { members, groupId, memberPath, canManageMembers } = el.dataset;
return {
members: convertObjectPropsToCamelCase(JSON.parse(members), { deep: true }),
sourceId: parseInt(groupId, 10),
memberPath,
+ canManageMembers: parseBoolean(canManageMembers),
};
};
diff --git a/app/assets/javascripts/groups/store/groups_store.js b/app/assets/javascripts/groups/store/groups_store.js
index 6a1197fa163..b6cea38e87f 100644
--- a/app/assets/javascripts/groups/store/groups_store.js
+++ b/app/assets/javascripts/groups/store/groups_store.js
@@ -1,11 +1,13 @@
import { normalizeHeaders, parseIntPagination } from '../../lib/utils/common_utils';
+import { getGroupItemMicrodata } from './utils';
export default class GroupsStore {
- constructor(hideProjects) {
+ constructor({ hideProjects = false, showSchemaMarkup = false } = {}) {
this.state = {};
this.state.groups = [];
this.state.pageInfo = {};
this.hideProjects = hideProjects;
+ this.showSchemaMarkup = showSchemaMarkup;
}
setGroups(rawGroups) {
@@ -94,6 +96,7 @@ export default class GroupsStore {
starCount: rawGroupItem.star_count,
updatedAt: rawGroupItem.updated_at,
pendingRemoval: rawGroupItem.marked_for_deletion,
+ microdata: this.showSchemaMarkup ? getGroupItemMicrodata(rawGroupItem) : {},
};
}
diff --git a/app/assets/javascripts/groups/store/utils.js b/app/assets/javascripts/groups/store/utils.js
new file mode 100644
index 00000000000..371b3aa9d52
--- /dev/null
+++ b/app/assets/javascripts/groups/store/utils.js
@@ -0,0 +1,27 @@
+export const getGroupItemMicrodata = ({ type }) => {
+ const defaultMicrodata = {
+ itemscope: true,
+ itemtype: 'https://schema.org/Thing',
+ itemprop: 'owns',
+ imageItemprop: 'image',
+ nameItemprop: 'name',
+ descriptionItemprop: 'description',
+ };
+
+ switch (type) {
+ case 'group':
+ return {
+ ...defaultMicrodata,
+ itemtype: 'https://schema.org/Organization',
+ itemprop: 'subOrganization',
+ imageItemprop: 'logo',
+ };
+ case 'project':
+ return {
+ ...defaultMicrodata,
+ itemtype: 'https://schema.org/SoftwareSourceCode',
+ };
+ default:
+ return defaultMicrodata;
+ }
+};
diff --git a/app/assets/javascripts/groups/visibility_level.js b/app/assets/javascripts/groups/visibility_level.js
new file mode 100644
index 00000000000..d570b5e65ac
--- /dev/null
+++ b/app/assets/javascripts/groups/visibility_level.js
@@ -0,0 +1,24 @@
+import Vue from 'vue';
+import VisibilityLevelDropdown from './components/visibility_level_dropdown.vue';
+
+export default () => {
+ const el = document.querySelector('.js-visibility-level-dropdown');
+
+ if (!el) {
+ return null;
+ }
+
+ const { visibilityLevelOptions, defaultLevel } = el.dataset;
+
+ return new Vue({
+ el,
+ render(createElement) {
+ return createElement(VisibilityLevelDropdown, {
+ props: {
+ visibilityLevelOptions: JSON.parse(visibilityLevelOptions),
+ defaultLevel: Number(defaultLevel),
+ },
+ });
+ },
+ });
+};