diff --git a/app/assets/javascripts/components/story/StoryCopyIdClipboard.js b/app/assets/javascripts/components/story/StoryCopyIdClipboard.js
new file mode 100644
index 000000000..7a0178176
--- /dev/null
+++ b/app/assets/javascripts/components/story/StoryCopyIdClipboard.js
@@ -0,0 +1,15 @@
+import React from 'react';
+import Clipboard from 'react-clipboard.js';
+
+const StoryCopyIdClipboard = ({ id }) => (
+
+ #{id}
+
+);
+
+export default StoryCopyIdClipboard;
diff --git a/app/assets/javascripts/templates/story.ejs b/app/assets/javascripts/templates/story.ejs
index 9accddcd7..552d0f34b 100644
--- a/app/assets/javascripts/templates/story.ejs
+++ b/app/assets/javascripts/templates/story.ejs
@@ -43,6 +43,7 @@
+
<% if (story.get('labels')) { %>
<% _.each(story.labels(), function(value) { %>
diff --git a/app/assets/javascripts/views/story_view.jsx b/app/assets/javascripts/views/story_view.jsx
index 98ea5cfb3..ed4039291 100644
--- a/app/assets/javascripts/views/story_view.jsx
+++ b/app/assets/javascripts/views/story_view.jsx
@@ -19,6 +19,7 @@ import storyTemplate from 'templates/story.ejs';
import alertTemplate from 'templates/alert.ejs';
import storyHoverTemplate from 'templates/story_hover.ejs';
import noteTemplate from 'templates/note.ejs';
+import StoryCopyIdClipboard from '../components/story/StoryCopyIdClipboard';
const LOCAL_STORY_REGEXP = /(?!\s|\b)(#\d+)(?!\w)/g;
@@ -541,7 +542,21 @@ const StoryView = FormView.extend({
);
},
- renderCollapsed: function (isGuest) {
+ appendAttachments: function() {
+ this.$el.append(
+ this.makeFormControl(function(div) {
+ const $storyAttachments = $('');
+ $(div).append($storyAttachments);
+
+ if(process.env.NODE_ENV !== 'test') {
+ clearTimeout(window.executeAttachinaryTimeout);
+ window.executeAttachinaryTimeout = setTimeout(ExecuteAttachinary, 1000);
+ }
+ })
+ );
+ },
+
+ renderCollapsed: function(isGuest) {
this.$el.removeClass('editing');
this.$el.html(this.template({ story: this.model, view: this }));
this.$el.toggleClass(
@@ -560,14 +575,16 @@ const StoryView = FormView.extend({
const estimateButtons = this.$('[data-story-estimate-buttons]').get(0);
if (estimateButtons) {
ReactDOM.render(
- ,
+ ,
estimateButtons
);
}
+ const copyStoryIdClipboardLink = this.$('[data-story-id-copy-clipboard]').get(0)
+ if(copyStoryIdClipboardLink) {
+ ReactDOM.render(, copyStoryIdClipboardLink)
+ }
+
if (isGuest) {
this.$el
.find('.state-actions')
diff --git a/app/assets/stylesheets/_screen.scss b/app/assets/stylesheets/_screen.scss
index 9474a044b..b678168f6 100644
--- a/app/assets/stylesheets/_screen.scss
+++ b/app/assets/stylesheets/_screen.scss
@@ -224,10 +224,14 @@ div.story-controls {
}
div.story-title {
- margin-left: 65px;
+ margin-left: 50px;
word-wrap: break-word;
}
+div.story-title div[data-story-id-copy-clipboard] {
+ display: inline;
+}
+
.unestimated div.story-title {
font-style: italic;
}
@@ -239,6 +243,19 @@ div.story-title abbr.initials {
border: none;
}
+div.story-title {
+ .story-id {
+ cursor: pointer;
+ color: $blue-4;
+ font-weight: bold;
+ border: none;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+}
+
.input-group-btn .btn-clipboard-id {
padding-top: 6px;
}
diff --git a/spec/javascripts/components/story/story_copy_id_clipboard_spec.js b/spec/javascripts/components/story/story_copy_id_clipboard_spec.js
new file mode 100644
index 000000000..27bde9a9e
--- /dev/null
+++ b/spec/javascripts/components/story/story_copy_id_clipboard_spec.js
@@ -0,0 +1,36 @@
+import React from 'react';
+import { mount, shallow } from 'enzyme';
+
+import StoryCopyIdClipboard from 'components/story/StoryCopyIdClipboard';
+
+describe('', function() {
+ beforeEach(function() {
+ sinon.stub(I18n, 't');
+ });
+
+ afterEach(function() {
+ I18n.t.restore();
+ });
+
+ it("should render story id text", function() {
+ const wrapper = mount(
+
+ );
+ expect(wrapper.find('.story-id').at(0).text()).toBe('#70');
+ });
+
+ it("should render story id data-clipboard-text", function() {
+ const wrapper = mount(
+
+ );
+ expect(wrapper.find('[data-clipboard-text]')).toExist();
+ });
+
+ it("should render copy id title", function() {
+ shallow(
+
+ );
+ expect(I18n.t).toHaveBeenCalledWith('story.events.copy_id');
+ });
+
+});