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:
authorSimon Knox <psimyn@gmail.com>2019-06-11 07:15:08 +0300
committerSimon Knox <psimyn@gmail.com>2019-06-14 16:57:05 +0300
commit14f27102b696672f02b5d1b2ab45688b711f4024 (patch)
treeeef48bb1366b20a961e6aa4bb61bc357dc77d1c9
parent577832598f1b35187efafc426068ef7ac36ae09f (diff)
Add Join meeting button to Issues with Zoom links
Detect links containing zoom.us followed by j, s, or my Add link below Issue title that links to Zoom meeting
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue3
-rw-r--r--app/assets/javascripts/issue_show/components/pinned_links.vue52
-rw-r--r--app/assets/stylesheets/framework/common.scss1
-rw-r--r--changelogs/unreleased/62966-embed-zoom-call-in-issue-mvc.yml5
-rw-r--r--locale/gitlab.pot3
-rw-r--r--package.json2
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb13
-rw-r--r--spec/frontend/issue_show/components/pinned_links_spec.js91
-rw-r--r--yarn.lock8
9 files changed, 173 insertions, 5 deletions
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index e88ca4747c5..de2a9664cde 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -11,6 +11,7 @@ import titleComponent from './title.vue';
import descriptionComponent from './description.vue';
import editedComponent from './edited.vue';
import formComponent from './form.vue';
+import PinnedLinks from './pinned_links.vue';
import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
export default {
@@ -19,6 +20,7 @@ export default {
titleComponent,
editedComponent,
formComponent,
+ PinnedLinks,
},
mixins: [recaptchaModalImplementor],
props: {
@@ -340,6 +342,7 @@ export default {
:title-text="state.titleText"
:show-inline-edit-button="showInlineEditButton"
/>
+ <pinned-links :description-html="state.descriptionHtml" />
<description-component
v-if="state.descriptionHtml"
:can-update="canUpdate"
diff --git a/app/assets/javascripts/issue_show/components/pinned_links.vue b/app/assets/javascripts/issue_show/components/pinned_links.vue
new file mode 100644
index 00000000000..7a54b26bc2b
--- /dev/null
+++ b/app/assets/javascripts/issue_show/components/pinned_links.vue
@@ -0,0 +1,52 @@
+<script>
+import { GlLink } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
+
+export default {
+ components: {
+ Icon,
+ GlLink,
+ },
+ props: {
+ descriptionHtml: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ linksInDescription() {
+ const el = document.createElement('div');
+ el.innerHTML = this.descriptionHtml;
+ return [...el.querySelectorAll('a')].map(a => a.href);
+ },
+ // Detect links matching the following formats:
+ // Zoom Start links: https://zoom.us/s/<meeting-id>
+ // Zoom Join links: https://zoom.us/j/<meeting-id>
+ // Personal Zoom links: https://zoom.us/my/<meeting-id>
+ // Vanity Zoom links: https://gitlab.zoom.us/j/<meeting-id> (also /s and /my)
+ zoomHref() {
+ const zoomRegex = /^https:\/\/([\w\d-]+\.)?zoom\.us\/(s|j|my)\/.+/;
+ return this.linksInDescription.reduce((acc, currentLink) => {
+ let lastLink = acc;
+ if (zoomRegex.test(currentLink)) {
+ lastLink = currentLink;
+ }
+ return lastLink;
+ }, '');
+ },
+ },
+};
+</script>
+
+<template>
+ <div v-if="zoomHref" class="border-bottom mb-3 mt-n2">
+ <gl-link
+ :href="zoomHref"
+ target="_blank"
+ class="btn btn-inverted btn-secondary btn-sm text-dark mb-3"
+ >
+ <icon name="brand-zoom" :size="14" />
+ <strong class="vertical-align-top">{{ __('Join Zoom meeting') }}</strong>
+ </gl-link>
+ </div>
+</template>
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index db09118ba15..1bd5043ed10 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -416,6 +416,7 @@ img.emoji {
.center { text-align: center; }
.block { display: block; }
.flex { display: flex; }
+.vertical-align-top { vertical-align: top; }
.vertical-align-middle { vertical-align: middle; }
.vertical-align-sub { vertical-align: sub; }
.flex-align-self-center { align-self: center; }
diff --git a/changelogs/unreleased/62966-embed-zoom-call-in-issue-mvc.yml b/changelogs/unreleased/62966-embed-zoom-call-in-issue-mvc.yml
new file mode 100644
index 00000000000..a41873f671e
--- /dev/null
+++ b/changelogs/unreleased/62966-embed-zoom-call-in-issue-mvc.yml
@@ -0,0 +1,5 @@
+---
+title: Add Join meeting button to issues with Zoom links
+merge_request: 29454
+author:
+type: added
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 88ace6057cf..3791691a611 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5594,6 +5594,9 @@ msgstr ""
msgid "Job|with"
msgstr ""
+msgid "Join Zoom meeting"
+msgstr ""
+
msgid "Jul"
msgstr ""
diff --git a/package.json b/package.json
index 0758c27c75b..a981a9058ae 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,7 @@
"@babel/plugin-syntax-import-meta": "^7.2.0",
"@babel/preset-env": "^7.4.4",
"@gitlab/csslab": "^1.9.0",
- "@gitlab/svgs": "^1.63.0",
+ "@gitlab/svgs": "^1.64.0",
"@gitlab/ui": "^3.11.0",
"apollo-cache-inmemory": "^1.5.1",
"apollo-client": "^2.5.1",
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index 0f604db870f..2789d574156 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -92,6 +92,19 @@ describe "User creates issue" do
.and have_content(label_titles.first)
end
end
+
+ context "with Zoom link" do
+ it "adds Zoom button" do
+ issue_title = "Issue containing Zoom meeting link"
+ zoom_url = "https://gitlab.zoom.us/j/123456789"
+
+ fill_in("Title", with: issue_title)
+ fill_in("Description", with: zoom_url)
+ click_button("Submit issue")
+
+ expect(page).to have_link('Join Zoom meeting', href: zoom_url)
+ end
+ end
end
context "when signed in as user with special characters in their name" do
diff --git a/spec/frontend/issue_show/components/pinned_links_spec.js b/spec/frontend/issue_show/components/pinned_links_spec.js
new file mode 100644
index 00000000000..50041667a61
--- /dev/null
+++ b/spec/frontend/issue_show/components/pinned_links_spec.js
@@ -0,0 +1,91 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlLink } from '@gitlab/ui';
+import PinnedLinks from '~/issue_show/components/pinned_links.vue';
+
+const localVue = createLocalVue();
+
+const plainZoomUrl = 'https://zoom.us/j/123456789';
+const vanityZoomUrl = 'https://gitlab.zoom.us/j/123456789';
+const startZoomUrl = 'https://zoom.us/s/123456789';
+const personalZoomUrl = 'https://zoom.us/my/hunter-zoloman';
+const randomUrl = 'https://zoom.us.com';
+
+describe('PinnedLinks', () => {
+ let wrapper;
+
+ const link = {
+ get text() {
+ return wrapper.find(GlLink).text();
+ },
+ get href() {
+ return wrapper.find(GlLink).attributes('href');
+ },
+ };
+
+ const createComponent = props => {
+ wrapper = shallowMount(localVue.extend(PinnedLinks), {
+ localVue,
+ sync: false,
+ propsData: {
+ descriptionHtml: '',
+ ...props,
+ },
+ });
+ };
+
+ it('displays Zoom link', () => {
+ createComponent({
+ descriptionHtml: `<a href="${plainZoomUrl}">Zoom</a>`,
+ });
+
+ expect(link.text).toBe('Join Zoom meeting');
+ });
+
+ it('detects plain Zoom link', () => {
+ createComponent({
+ descriptionHtml: `<a href="${plainZoomUrl}">Zoom</a>`,
+ });
+
+ expect(link.href).toBe(plainZoomUrl);
+ });
+
+ it('detects vanity Zoom link', () => {
+ createComponent({
+ descriptionHtml: `<a href="${vanityZoomUrl}">Zoom</a>`,
+ });
+
+ expect(link.href).toBe(vanityZoomUrl);
+ });
+
+ it('detects Zoom start meeting link', () => {
+ createComponent({
+ descriptionHtml: `<a href="${startZoomUrl}">Zoom</a>`,
+ });
+
+ expect(link.href).toBe(startZoomUrl);
+ });
+
+ it('detects personal Zoom room link', () => {
+ createComponent({
+ descriptionHtml: `<a href="${personalZoomUrl}">Zoom</a>`,
+ });
+
+ expect(link.href).toBe(personalZoomUrl);
+ });
+
+ it('only renders final Zoom link in description', () => {
+ createComponent({
+ descriptionHtml: `<a href="${plainZoomUrl}">Zoom</a><a href="${vanityZoomUrl}">Zoom</a>`,
+ });
+
+ expect(link.href).toBe(vanityZoomUrl);
+ });
+
+ it('does not render for other links', () => {
+ createComponent({
+ descriptionHtml: `<a href="${randomUrl}">Some other link</a>`,
+ });
+
+ expect(wrapper.find(GlLink).exists()).toBe(false);
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index dddf01414b2..f97e7363331 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -700,10 +700,10 @@
dependencies:
requireindex "~1.1.0"
-"@gitlab/svgs@^1.63.0":
- version "1.63.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.63.0.tgz#9dd544026d203e4ce6efed72b05db68f710c4d49"
- integrity sha512-YztrReFTg31B7v5wtUC5j15KHNcMebtW+kACytEU42XomMaIwk4USIbygqWlq0VRHA2VHJrHApfJHIjxiCCQcA==
+"@gitlab/svgs@^1.64.0":
+ version "1.64.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.64.0.tgz#1370bcbe9ca0ecc9fb919956cd4241bea090ddd3"
+ integrity sha512-y9p73NGDnQJc18Dtk0oJfgxedancBT6UceATcnZMceLV6iWylzdMbQWxCl4O2aBXwsAoCrLUJQ9jhRkbNicYNA==
"@gitlab/ui@^3.11.0":
version "3.11.0"