diff options
Diffstat (limited to 'app/assets/javascripts/pages/projects/learn_gitlab')
6 files changed, 201 insertions, 16 deletions
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue index 32ca623ca45..ef9e13f7ccf 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_a.vue @@ -1,11 +1,17 @@ <script> -import { GlLink } from '@gitlab/ui'; -import { ACTION_LABELS } from '../constants'; +import { GlProgressBar, GlSprintf } from '@gitlab/ui'; +import { s__ } from '~/locale'; +import { ACTION_LABELS, ACTION_SECTIONS } from '../constants'; +import LearnGitlabSectionCard from './learn_gitlab_section_card.vue'; export default { - components: { GlLink }, + components: { GlProgressBar, GlSprintf, LearnGitlabSectionCard }, i18n: { - ACTION_LABELS, + title: s__('LearnGitLab|Learn GitLab'), + description: s__( + 'LearnGitLab|Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project.', + ), + percentageCompleted: s__(`LearnGitLab|%{percentage}%{percentSymbol} completed`), }, props: { actions: { @@ -13,15 +19,49 @@ export default { type: Object, }, }, + maxValue: Object.keys(ACTION_LABELS).length, + sections: Object.keys(ACTION_SECTIONS), + computed: { + progressValue() { + return Object.values(this.actions).filter((a) => a.completed).length; + }, + progressPercentage() { + return Math.round((this.progressValue / this.$options.maxValue) * 100); + }, + }, + methods: { + actionsFor(section) { + const actions = Object.fromEntries( + Object.entries(this.actions).filter( + ([action]) => ACTION_LABELS[action].section === section, + ), + ); + return actions; + }, + }, }; </script> <template> - <ul> - <li v-for="(value, action) in actions" :key="action"> - <span v-if="value.completed">{{ $options.i18n.ACTION_LABELS[action].title }}</span> - <span v-else> - <gl-link :href="value.url">{{ $options.i18n.ACTION_LABELS[action].title }}</gl-link> - </span> - </li> - </ul> + <div> + <div class="row"> + <div class="gl-mb-7 gl-ml-5"> + <h1 class="gl-font-size-h1">{{ $options.i18n.title }}</h1> + <p class="gl-text-gray-700 gl-mb-0">{{ $options.i18n.description }}</p> + </div> + </div> + <div class="gl-mb-3"> + <p class="gl-text-gray-500 gl-mb-2" data-testid="completion-percentage"> + <gl-sprintf :message="$options.i18n.percentageCompleted"> + <template #percentage>{{ progressPercentage }}</template> + <template #percentSymbol>%</template> + </gl-sprintf> + </p> + <gl-progress-bar :value="progressValue" :max="$options.maxValue" /> + </div> + <div class="row row-cols-1 row-cols-md-3 gl-mt-5"> + <div v-for="section in $options.sections" :key="section" class="col gl-mb-6"> + <learn-gitlab-section-card :section="section" :actions="actionsFor(section)" /> + </div> + </div> + </div> </template> diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue index 230054ff76e..8f92ce95dbf 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_b.vue @@ -1,5 +1,6 @@ <script> import { GlProgressBar, GlSprintf } from '@gitlab/ui'; +import { pick } from 'lodash'; import { s__ } from '~/locale'; import { ACTION_LABELS } from '../constants'; import LearnGitlabInfoCard from './learn_gitlab_info_card.vue'; @@ -42,7 +43,7 @@ export default { infoProps(action) { return { ...this.actions[action], - ...ACTION_LABELS[action], + ...pick(ACTION_LABELS[action], ['title', 'actionLabel', 'description', 'trialRequired']), }; }, progressValue() { @@ -96,6 +97,9 @@ export default { <div class="row row-cols-2 row-cols-md-3 row-cols-lg-4"> <div class="col gl-mb-6"> + <learn-gitlab-info-card v-bind="infoProps('issueCreated')" /> + </div> + <div class="col gl-mb-6"> <learn-gitlab-info-card v-bind="infoProps('mergeRequestCreated')" /> </div> </div> diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue index 3d2a8eed9d4..6cd3bbc359b 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_info_card.vue @@ -61,7 +61,7 @@ export default { <div class="gl-text-center gl-display-flex gl-justify-content-center gl-align-items-center gl-flex-direction-column learn-gitlab-info-card-content" > - <img :src="svg" /> + <img :src="svg" :alt="actionLabel" /> <h6>{{ title }}</h6> <p class="gl-font-sm gl-text-gray-700">{{ description }}</p> <gl-link :href="url" target="_blank">{{ actionLabel }}</gl-link> diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue new file mode 100644 index 00000000000..db694a66afd --- /dev/null +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue @@ -0,0 +1,52 @@ +<script> +import { GlCard } from '@gitlab/ui'; +import { imagePath } from '~/lib/utils/common_utils'; +import { ACTION_LABELS, ACTION_SECTIONS } from '../constants'; + +import LearnGitlabSectionLink from './learn_gitlab_section_link.vue'; + +export default { + name: 'LearnGitlabSectionCard', + components: { GlCard, LearnGitlabSectionLink }, + i18n: { + ...ACTION_SECTIONS, + }, + props: { + section: { + required: true, + type: String, + }, + actions: { + required: true, + type: Object, + }, + }, + computed: { + sortedActions() { + return Object.entries(this.actions).sort( + (a1, a2) => ACTION_LABELS[a1[0]].position - ACTION_LABELS[a2[0]].position, + ); + }, + }, + methods: { + svg(section) { + return imagePath(`learn_gitlab/section_${section}.svg`); + }, + }, +}; +</script> +<template> + <gl-card class="gl-pt-0 learn-gitlab-section-card"> + <div class="learn-gitlab-section-card-header"> + <img :src="svg(section)" /> + <h2 class="gl-font-lg gl-mb-3">{{ $options.i18n[section].title }}</h2> + <p class="gl-text-gray-700 gl-mb-6">{{ $options.i18n[section].description }}</p> + </div> + <learn-gitlab-section-link + v-for="[action, value] in sortedActions" + :key="action" + :action="action" + :value="value" + /> + </gl-card> +</template> diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue new file mode 100644 index 00000000000..6f51c7372fd --- /dev/null +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue @@ -0,0 +1,43 @@ +<script> +import { GlLink, GlIcon } from '@gitlab/ui'; +import { s__ } from '~/locale'; +import { ACTION_LABELS } from '../constants'; + +export default { + name: 'LearnGitlabSectionLink', + components: { GlLink, GlIcon }, + i18n: { + ACTION_LABELS, + trialOnly: s__('LearnGitlab|Trial only'), + }, + props: { + action: { + required: true, + type: String, + }, + value: { + required: true, + type: Object, + }, + }, + computed: { + trialOnly() { + return ACTION_LABELS[this.action].trialRequired; + }, + }, +}; +</script> +<template> + <div class="gl-mb-4"> + <span v-if="value.completed" class="gl-text-green-500"> + <gl-icon name="check-circle-filled" :size="16" data-testid="completed-icon" /> + {{ $options.i18n.ACTION_LABELS[action].title }} + </span> + <span v-else> + <gl-link :href="value.url">{{ $options.i18n.ACTION_LABELS[action].title }}</gl-link> + </span> + <span v-if="trialOnly" class="gl-font-style-italic gl-text-gray-500" data-testid="trial-only"> + - {{ $options.i18n.trialOnly }} + </span> + </div> +</template> diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js index 80f04b0cf44..9e204aa6746 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js +++ b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js @@ -5,6 +5,8 @@ export const ACTION_LABELS = { title: s__('LearnGitLab|Create or import a repository'), actionLabel: s__('LearnGitLab|Create or import a repository'), description: s__('LearnGitLab|Create or import your first repository into your new project.'), + section: 'workspace', + position: 1, }, userAdded: { title: s__('LearnGitLab|Invite your colleagues'), @@ -12,16 +14,22 @@ export const ACTION_LABELS = { description: s__( 'LearnGitLab|GitLab works best as a team. Invite your colleague to enjoy all features.', ), + section: 'workspace', + position: 0, }, pipelineCreated: { title: s__('LearnGitLab|Set up CI/CD'), actionLabel: s__('LearnGitLab|Set-up CI/CD'), description: s__('LearnGitLab|Save time by automating your integration and deployment tasks.'), + section: 'workspace', + position: 2, }, trialStarted: { title: s__('LearnGitLab|Start a free Ultimate trial'), actionLabel: s__('LearnGitLab|Try GitLab Ultimate for free'), description: s__('LearnGitLab|Try all GitLab features for 30 days, no credit card required.'), + section: 'workspace', + position: 3, }, codeOwnersEnabled: { title: s__('LearnGitLab|Add code owners'), @@ -30,21 +38,59 @@ export const ACTION_LABELS = { 'LearnGitLab|Prevent unexpected changes to important assets by assigning ownership of files and paths.', ), trialRequired: true, + section: 'workspace', + position: 4, }, requiredMrApprovalsEnabled: { title: s__('LearnGitLab|Add merge request approval'), actionLabel: s__('LearnGitLab|Enable require merge approvals'), description: s__('LearnGitLab|Route code reviews to the right reviewers, every time.'), trialRequired: true, + section: 'workspace', + position: 5, }, mergeRequestCreated: { title: s__('LearnGitLab|Submit a merge request'), actionLabel: s__('LearnGitLab|Submit a merge request (MR)'), description: s__('LearnGitLab|Review and edit proposed changes to source code.'), + section: 'plan', + position: 1, }, securityScanEnabled: { - title: s__('LearnGitLab|Run a security scan'), - actionLabel: s__('LearnGitLab|Run a Security scan'), + title: s__('LearnGitLab|Run a Security scan using CI/CD'), + actionLabel: s__('LearnGitLab|Run a Security scan using CI/CD'), description: s__('LearnGitLab|Scan your code to uncover vulnerabilities before deploying.'), + section: 'deploy', + position: 1, + }, + issueCreated: { + title: s__('LearnGitLab|Create an issue'), + actionLabel: s__('LearnGitLab|Create an issue'), + description: s__( + 'LearnGitLab|Create/import issues (tickets) to collaborate on ideas and plan work.', + ), + section: 'plan', + position: 0, + }, +}; + +export const ACTION_SECTIONS = { + workspace: { + title: s__('LearnGitLab|Set up your workspace'), + description: s__( + "LearnGitLab|Complete these tasks first so you can enjoy GitLab's features to their fullest:", + ), + }, + plan: { + title: s__('LearnGitLab|Plan and execute'), + description: s__( + 'LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:', + ), + }, + deploy: { + title: s__('LearnGitLab|Deploy'), + description: s__( + 'LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:', + ), }, }; |