diff options
Diffstat (limited to 'app')
11 files changed, 158 insertions, 24 deletions
diff --git a/app/assets/javascripts/ci/catalog/components/list/catalog_header.vue b/app/assets/javascripts/ci/catalog/components/list/catalog_header.vue index 20a62d0eeb2..64229f54904 100644 --- a/app/assets/javascripts/ci/catalog/components/list/catalog_header.vue +++ b/app/assets/javascripts/ci/catalog/components/list/catalog_header.vue @@ -6,7 +6,7 @@ import { CATALOG_FEEDBACK_DISMISSED_KEY } from '../../constants'; const defaultTitle = __('CI/CD Catalog'); const defaultDescription = s__( - 'CiCatalog|Discover CI configuration resources for a seamless CI/CD experience.', + 'CiCatalog|Discover CI/CD components that can improve your pipeline with additional functionality.', ); export default { @@ -45,7 +45,7 @@ export default { }; </script> <template> - <div> + <div class="page-title-holder"> <gl-banner v-if="!isFeedbackBannerDismissed" class="gl-mt-5" @@ -58,7 +58,7 @@ export default { {{ $options.i18n.banner.description }} </p> </gl-banner> - <h1 class="gl-font-size-h-display">{{ pageTitle }}</h1> + <h1 class="page-title gl-font-size-h-display">{{ pageTitle }}</h1> <p> <span data-testid="page-description">{{ pageDescription }}</span> <gl-link :href="$options.learnMorePath" target="_blank">{{ diff --git a/app/assets/javascripts/organizations/index/components/app.vue b/app/assets/javascripts/organizations/index/components/app.vue index c47f4ed52c5..4935e0122e3 100644 --- a/app/assets/javascripts/organizations/index/components/app.vue +++ b/app/assets/javascripts/organizations/index/components/app.vue @@ -2,6 +2,7 @@ import { GlButton } from '@gitlab/ui'; import { __, s__ } from '~/locale'; import { createAlert } from '~/alert'; +import { DEFAULT_PER_PAGE } from '~/api'; import organizationsQuery from '../graphql/organizations.query.graphql'; import OrganizationsView from './organizations_view.vue'; @@ -21,14 +22,23 @@ export default { inject: ['newOrganizationUrl'], data() { return { - organizations: [], + organizations: {}, + pagination: { + first: DEFAULT_PER_PAGE, + after: null, + last: null, + before: null, + }, }; }, apollo: { organizations: { query: organizationsQuery, + variables() { + return this.pagination; + }, update(data) { - return data.currentUser.organizations.nodes; + return data.currentUser.organizations; }, error(error) { createAlert({ message: this.$options.i18n.errorMessage, error, captureError: true }); @@ -37,12 +47,30 @@ export default { }, computed: { showHeader() { - return this.loading || this.organizations.length; + return this.loading || this.organizations.nodes?.length; }, loading() { return this.$apollo.queries.organizations.loading; }, }, + methods: { + onNext(endCursor) { + this.pagination = { + first: DEFAULT_PER_PAGE, + after: endCursor, + last: null, + before: null, + }; + }, + onPrev(startCursor) { + this.pagination = { + first: null, + after: null, + last: DEFAULT_PER_PAGE, + before: startCursor, + }; + }, + }, }; </script> @@ -56,6 +84,11 @@ export default { }}</gl-button> </div> </div> - <organizations-view :organizations="organizations" :loading="loading" /> + <organizations-view + :organizations="organizations" + :loading="loading" + @next="onNext" + @prev="onPrev" + /> </section> </template> diff --git a/app/assets/javascripts/organizations/index/components/organizations_list.vue b/app/assets/javascripts/organizations/index/components/organizations_list.vue index 539a4fcfe29..971d4710be2 100644 --- a/app/assets/javascripts/organizations/index/components/organizations_list.vue +++ b/app/assets/javascripts/organizations/index/components/organizations_list.vue @@ -1,26 +1,52 @@ <script> +import { GlKeysetPagination } from '@gitlab/ui'; +import { __ } from '~/locale'; import OrganizationsListItem from './organizations_list_item.vue'; export default { name: 'OrganizationsList', components: { OrganizationsListItem, + GlKeysetPagination, + }, + i18n: { + prev: __('Prev'), + next: __('Next'), }, props: { organizations: { - type: Array, + type: Object, required: true, }, }, + computed: { + nodes() { + return this.organizations.nodes || []; + }, + pageInfo() { + return this.organizations.pageInfo || {}; + }, + }, }; </script> <template> - <ul class="gl-p-0 gl-list-style-none"> - <organizations-list-item - v-for="organization in organizations" - :key="organization.id" - :organization="organization" - /> - </ul> + <div> + <ul class="gl-p-0 gl-list-style-none"> + <organizations-list-item + v-for="organization in nodes" + :key="organization.id" + :organization="organization" + /> + </ul> + <div v-if="pageInfo.hasNextPage || pageInfo.hasPreviousPage" class="gl-text-center gl-mt-5"> + <gl-keyset-pagination + v-bind="pageInfo" + :prev-text="$options.i18n.prev" + :next-text="$options.i18n.next" + @prev="$emit('prev', $event)" + @next="$emit('next', $event)" + /> + </div> + </div> </template> diff --git a/app/assets/javascripts/organizations/index/components/organizations_view.vue b/app/assets/javascripts/organizations/index/components/organizations_view.vue index 9720646bca3..59e94670826 100644 --- a/app/assets/javascripts/organizations/index/components/organizations_view.vue +++ b/app/assets/javascripts/organizations/index/components/organizations_view.vue @@ -20,9 +20,9 @@ export default { inject: ['newOrganizationUrl', 'organizationsEmptyStateSvgPath'], props: { organizations: { - type: Array, + type: Object, required: false, - default: () => [], + default: () => {}, }, loading: { type: Boolean, @@ -30,15 +30,22 @@ export default { default: false, }, }, + computed: { + nodes() { + return this.organizations.nodes || []; + }, + }, }; </script> <template> <gl-loading-icon v-if="loading" class="gl-mt-5" size="md" /> <organizations-list - v-else-if="organizations.length" + v-else-if="nodes.length" :organizations="organizations" class="gl-border-t" + @prev="$emit('prev', $event)" + @next="$emit('next', $event)" /> <gl-empty-state v-else diff --git a/app/assets/javascripts/organizations/index/graphql/organizations.query.graphql b/app/assets/javascripts/organizations/index/graphql/organizations.query.graphql index 6090e2ec789..0673acc5014 100644 --- a/app/assets/javascripts/organizations/index/graphql/organizations.query.graphql +++ b/app/assets/javascripts/organizations/index/graphql/organizations.query.graphql @@ -1,7 +1,7 @@ -query getCurrentUserOrganizations { +query getCurrentUserOrganizations($first: Int, $last: Int, $before: String, $after: String) { currentUser { id - organizations @client { + organizations(first: $first, last: $last, before: $before, after: $after) { nodes { id name @@ -9,6 +9,12 @@ query getCurrentUserOrganizations { avatarUrl webUrl } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } } } } diff --git a/app/assets/javascripts/organizations/index/graphql/organizations_client.query.graphql b/app/assets/javascripts/organizations/index/graphql/organizations_client.query.graphql new file mode 100644 index 00000000000..66f7a82380c --- /dev/null +++ b/app/assets/javascripts/organizations/index/graphql/organizations_client.query.graphql @@ -0,0 +1,14 @@ +query getCurrentUserOrganizationsClient { + currentUser { + id + organizations @client { + nodes { + id + name + descriptionHtml + avatarUrl + webUrl + } + } + } +} diff --git a/app/assets/javascripts/organizations/index/index.js b/app/assets/javascripts/organizations/index/index.js index 7cbb9c9165d..df9ed2a4cce 100644 --- a/app/assets/javascripts/organizations/index/index.js +++ b/app/assets/javascripts/organizations/index/index.js @@ -2,7 +2,6 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; -import resolvers from '../shared/graphql/resolvers'; import OrganizationsIndexApp from './components/app.vue'; export const initOrganizationsIndex = () => { @@ -11,7 +10,7 @@ export const initOrganizationsIndex = () => { if (!el) return false; const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient(resolvers), + defaultClient: createDefaultClient(), }); const { newOrganizationUrl, organizationsEmptyStateSvgPath } = convertObjectPropsToCamelCase( diff --git a/app/assets/javascripts/organizations/mock_data.js b/app/assets/javascripts/organizations/mock_data.js index 725b6ac1ad8..7080170958b 100644 --- a/app/assets/javascripts/organizations/mock_data.js +++ b/app/assets/javascripts/organizations/mock_data.js @@ -309,3 +309,24 @@ export const updateOrganizationResponse = { }, errors: [], }; + +export const pageInfo = { + endCursor: 'eyJpZCI6IjEwNTMifQ', + hasNextPage: true, + hasPreviousPage: true, + startCursor: 'eyJpZCI6IjEwNzIifQ', +}; + +export const pageInfoOnePage = { + endCursor: 'eyJpZCI6IjEwNTMifQ', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'eyJpZCI6IjEwNzIifQ', +}; + +export const pageInfoEmpty = { + endCursor: null, + hasNextPage: false, + hasPreviousPage: false, + startCursor: null, +}; diff --git a/app/assets/javascripts/vue_shared/components/entity_select/organization_select.vue b/app/assets/javascripts/vue_shared/components/entity_select/organization_select.vue index d068d86d95b..ba89de36595 100644 --- a/app/assets/javascripts/vue_shared/components/entity_select/organization_select.vue +++ b/app/assets/javascripts/vue_shared/components/entity_select/organization_select.vue @@ -1,7 +1,7 @@ <script> import { GlAlert } from '@gitlab/ui'; import * as Sentry from '~/sentry/sentry_browser_wrapper'; -import getCurrentUserOrganizationsQuery from '~/organizations/index/graphql/organizations.query.graphql'; +import getCurrentUserOrganizationsClientQuery from '~/organizations/index/graphql/organizations_client.query.graphql'; import getOrganizationQuery from '~/organizations/shared/graphql/queries/organization.query.graphql'; import { getIdFromGraphQLId, convertToGraphQLId } from '~/graphql_shared/utils'; import { TYPENAME_ORGANIZATION } from '~/graphql_shared/constants'; @@ -74,7 +74,7 @@ export default { }, }, } = await this.$apollo.query({ - query: getCurrentUserOrganizationsQuery, + query: getCurrentUserOrganizationsClientQuery, // TODO: implement search support - https://gitlab.com/gitlab-org/gitlab/-/issues/429999. }); diff --git a/app/graphql/types/organizations/organization_type.rb b/app/graphql/types/organizations/organization_type.rb index e7ba8de527c..01d5bd7b635 100644 --- a/app/graphql/types/organizations/organization_type.rb +++ b/app/graphql/types/organizations/organization_type.rb @@ -7,6 +7,20 @@ module Types authorize :read_organization + field :avatar_url, + type: GraphQL::Types::String, + null: true, + description: + 'Avatar URL of the organization. `null` until ' \ + '[#422418](https://gitlab.com/gitlab-org/gitlab/-/issues/422418) is complete.', + alpha: { milestone: '16.7' } + field :description, + GraphQL::Types::String, + null: true, + description: + 'Description of the organization. `null` until ' \ + '[#422078](https://gitlab.com/gitlab-org/gitlab/-/issues/422078) is complete.', + alpha: { milestone: '16.7' } field :groups, Types::GroupType.connection_type, null: false, @@ -37,6 +51,15 @@ module Types null: false, description: 'Web URL of the organization.', alpha: { milestone: '16.6' } + + # Returns empty string until https://gitlab.com/gitlab-org/gitlab/-/issues/422078 is complete. + markdown_field :description_html, + null: true + + # TODO - update to return real avatar url when https://gitlab.com/gitlab-org/gitlab/-/issues/422418 is complete. + def avatar_url + nil + end end end end diff --git a/app/models/organizations/organization.rb b/app/models/organizations/organization.rb index 157b851e009..4244f51bb2e 100644 --- a/app/models/organizations/organization.rb +++ b/app/models/organizations/organization.rb @@ -46,6 +46,11 @@ module Organizations Gitlab::UrlBuilder.build(self, only_path: only_path) end + # TODO - update to return real description when https://gitlab.com/gitlab-org/gitlab/-/issues/422078 is complete. + def description + nil + end + private def check_if_default_organization |