diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-16 00:14:31 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-16 00:14:31 +0300 |
commit | c568cb4dbc0421212a28f3cd5b77223aad8888ba (patch) | |
tree | be3ab3b5d6cf5c23a71b557ed82758c905a437bd /app | |
parent | 4481a56a94c579f52e1cdef1cc1f4995f0ee1412 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
10 files changed, 219 insertions, 8 deletions
diff --git a/app/assets/javascripts/crm/components/contacts_root.vue b/app/assets/javascripts/crm/components/contacts_root.vue index 6d32ba41eae..83c02f7d5fe 100644 --- a/app/assets/javascripts/crm/components/contacts_root.vue +++ b/app/assets/javascripts/crm/components/contacts_root.vue @@ -1,7 +1,80 @@ <script> -export default {}; +import { GlLoadingIcon, GlTable } from '@gitlab/ui'; +import createFlash from '~/flash'; +import { s__, __ } from '~/locale'; +import getGroupContactsQuery from './queries/get_group_contacts.query.graphql'; + +export default { + components: { + GlLoadingIcon, + GlTable, + }, + inject: ['groupFullPath'], + data() { + return { contacts: [] }; + }, + apollo: { + contacts: { + query() { + return getGroupContactsQuery; + }, + variables() { + return { + groupFullPath: this.groupFullPath, + }; + }, + update(data) { + return this.extractContacts(data); + }, + error(error) { + createFlash({ + message: __('Something went wrong. Please try again.'), + error, + captureError: true, + }); + }, + }, + }, + computed: { + isLoading() { + return this.$apollo.queries.contacts.loading; + }, + }, + methods: { + extractContacts(data) { + const contacts = data?.group?.contacts?.nodes || []; + return contacts.slice().sort((a, b) => a.firstName.localeCompare(b.firstName)); + }, + }, + fields: [ + { key: 'firstName', sortable: true }, + { key: 'lastName', sortable: true }, + { key: 'email', sortable: true }, + { key: 'phone', sortable: true }, + { key: 'description', sortable: true }, + { + key: 'organization', + formatter: (organization) => { + return organization?.name; + }, + sortable: true, + }, + ], + i18n: { + emptyText: s__('Crm|No contacts found'), + }, +}; </script> <template> - <div></div> + <div> + <gl-loading-icon v-if="isLoading" class="gl-mt-5" size="lg" /> + <gl-table + v-else + :items="contacts" + :fields="$options.fields" + :empty-text="$options.i18n.emptyText" + show-empty + /> + </div> </template> diff --git a/app/assets/javascripts/crm/components/queries/get_group_contacts.query.graphql b/app/assets/javascripts/crm/components/queries/get_group_contacts.query.graphql new file mode 100644 index 00000000000..f6acd258585 --- /dev/null +++ b/app/assets/javascripts/crm/components/queries/get_group_contacts.query.graphql @@ -0,0 +1,22 @@ +query contacts($groupFullPath: ID!) { + group(fullPath: $groupFullPath) { + __typename + id + contacts { + nodes { + __typename + id + firstName + lastName + email + phone + description + organization { + __typename + id + name + } + } + } + } +} diff --git a/app/assets/javascripts/crm/contacts_bundle.js b/app/assets/javascripts/crm/contacts_bundle.js index a46acfdc2d5..6438953596e 100644 --- a/app/assets/javascripts/crm/contacts_bundle.js +++ b/app/assets/javascripts/crm/contacts_bundle.js @@ -1,15 +1,25 @@ import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; import CrmContactsRoot from './components/contacts_root.vue'; +Vue.use(VueApollo); + export default () => { const el = document.getElementById('js-crm-contacts-app'); + const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient(), + }); + if (!el) { return false; } return new Vue({ el, + apolloProvider, + provide: { groupFullPath: el.dataset.groupFullPath }, render(createElement) { return createElement(CrmContactsRoot); }, diff --git a/app/assets/javascripts/projects/components/project_delete_button.vue b/app/assets/javascripts/projects/components/project_delete_button.vue index 06711e4025a..bac876317b8 100644 --- a/app/assets/javascripts/projects/components/project_delete_button.vue +++ b/app/assets/javascripts/projects/components/project_delete_button.vue @@ -18,12 +18,36 @@ export default { type: String, required: true, }, + isFork: { + type: Boolean, + required: true, + }, + issuesCount: { + type: Number, + required: true, + }, + mergeRequestsCount: { + type: Number, + required: true, + }, + forksCount: { + type: Number, + required: true, + }, + starsCount: { + type: Number, + required: true, + }, }, strings: { alertTitle: __('You are about to permanently delete this project'), alertBody: __( 'Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc.', ), + isNotForkMessage: __( + 'This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:', + ), + isForkMessage: __('This forked project has the following:'), }, }; </script> @@ -37,6 +61,38 @@ export default { :title="$options.strings.alertTitle" :dismissible="false" > + <p> + <gl-sprintf v-if="isFork" :message="$options.strings.isForkMessage" /> + <gl-sprintf v-else :message="$options.strings.isNotForkMessage"> + <template #strong="{ content }"> + <strong>{{ content }}</strong> + </template> + </gl-sprintf> + </p> + <ul> + <li> + <gl-sprintf :message="n__('%d issue', '%d issues', issuesCount)"> + <template #issuesCount>{{ issuesCount }}</template> + </gl-sprintf> + </li> + <li> + <gl-sprintf + :message="n__('%d merge requests', '%d merge requests', mergeRequestsCount)" + > + <template #mergeRequestsCount>{{ mergeRequestsCount }}</template> + </gl-sprintf> + </li> + <li> + <gl-sprintf :message="n__('%d fork', '%d forks', forksCount)"> + <template #forksCount>{{ forksCount }}</template> + </gl-sprintf> + </li> + <li> + <gl-sprintf :message="n__('%d star', '%d stars', starsCount)"> + <template #starsCount>{{ starsCount }}</template> + </gl-sprintf> + </li> + </ul> <gl-sprintf :message="$options.strings.alertBody"> <template #strong="{ content }"> <strong>{{ content }}</strong> diff --git a/app/assets/javascripts/projects/project_delete_button.js b/app/assets/javascripts/projects/project_delete_button.js index aa7fc31d307..b4d388eda3a 100644 --- a/app/assets/javascripts/projects/project_delete_button.js +++ b/app/assets/javascripts/projects/project_delete_button.js @@ -1,4 +1,5 @@ import Vue from 'vue'; +import { parseBoolean } from '~/lib/utils/common_utils'; import ProjectDeleteButton from './components/project_delete_button.vue'; export default (selector = '#js-project-delete-button') => { @@ -6,7 +7,15 @@ export default (selector = '#js-project-delete-button') => { if (!el) return; - const { confirmPhrase, formPath } = el.dataset; + const { + confirmPhrase, + formPath, + isFork, + issuesCount, + mergeRequestsCount, + forksCount, + starsCount, + } = el.dataset; // eslint-disable-next-line no-new new Vue({ @@ -16,6 +25,11 @@ export default (selector = '#js-project-delete-button') => { props: { confirmPhrase, formPath, + isFork: parseBoolean(isFork), + issuesCount: parseInt(issuesCount, 10), + mergeRequestsCount: parseInt(mergeRequestsCount, 10), + forksCount: parseInt(forksCount, 10), + starsCount: parseInt(starsCount, 10), }, }); }, diff --git a/app/controllers/jwks_controller.rb b/app/controllers/jwks_controller.rb index e7b839f5590..3b0e6ca2eb1 100644 --- a/app/controllers/jwks_controller.rb +++ b/app/controllers/jwks_controller.rb @@ -1,13 +1,17 @@ # frozen_string_literal: true -class JwksController < ActionController::Base # rubocop:disable Rails/ApplicationController +class JwksController < Doorkeeper::OpenidConnect::DiscoveryController def index - render json: { keys: keys } + render json: { keys: payload } + end + + def keys + index end private - def keys + def payload [ # We keep openid_connect_signing_key so that we can seamlessly # replace it with ci_jwt_signing_key and remove it on the next release. diff --git a/app/services/projects/all_issues_count_service.rb b/app/services/projects/all_issues_count_service.rb new file mode 100644 index 00000000000..15352b14d3e --- /dev/null +++ b/app/services/projects/all_issues_count_service.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Projects + # Service class for counting and caching the number of all issues of a + # project. + class AllIssuesCountService < Projects::CountService + def relation_for_count + @project.issues + end + + def cache_key_name + 'all_issues_count' + end + end +end diff --git a/app/services/projects/all_merge_requests_count_service.rb b/app/services/projects/all_merge_requests_count_service.rb new file mode 100644 index 00000000000..db0bab3f799 --- /dev/null +++ b/app/services/projects/all_merge_requests_count_service.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Projects + # Service class for counting and caching the number of all merge requests of + # a project. + class AllMergeRequestsCountService < Projects::CountService + def relation_for_count + @project.merge_requests + end + + def cache_key_name + 'all_merge_requests_count' + end + end +end diff --git a/app/views/groups/crm/contacts.html.haml b/app/views/groups/crm/contacts.html.haml index f4189612694..c452a969d17 100644 --- a/app/views/groups/crm/contacts.html.haml +++ b/app/views/groups/crm/contacts.html.haml @@ -1,4 +1,4 @@ - breadcrumb_title _('Customer Relations Contacts') - page_title _('Customer Relations Contacts') -#js-crm-contacts-app +#js-crm-contacts-app{ data: { group_full_path: @group.full_path } } diff --git a/app/views/projects/_remove.html.haml b/app/views/projects/_remove.html.haml index ef4a90a5c08..815e76ebcb9 100644 --- a/app/views/projects/_remove.html.haml +++ b/app/views/projects/_remove.html.haml @@ -1,4 +1,6 @@ - return unless can?(current_user, :remove_project, project) +- merge_requests_count = Projects::AllMergeRequestsCountService.new(project).count +- issues_count = Projects::AllIssuesCountService.new(project).count .sub-section %h4.danger-title= _('Delete project') @@ -7,4 +9,4 @@ = link_to _('Learn more.'), help_page_path('user/project/settings/index', anchor: 'removing-a-fork-relationship'), target: '_blank', rel: 'noopener noreferrer' %p %strong= _('Deleted projects cannot be restored!') - #js-project-delete-button{ data: { form_path: project_path(project), confirm_phrase: delete_confirm_phrase(project) } } + #js-project-delete-button{ data: { form_path: project_path(project), confirm_phrase: delete_confirm_phrase(project), is_fork: project.forked?.to_s, issues_count: number_with_delimiter(issues_count), merge_requests_count: number_with_delimiter(merge_requests_count), forks_count: number_with_delimiter(project.forks_count), stars_count: number_with_delimiter(project.star_count) } } |