FEATURE: Shared Drafts

This feature can be enabled by choosing a destination for the
`shared drafts category` site setting.

* Staff members can create shared drafts, choosing a destination
category for the topic when it is published.

* Shared Drafts can be viewed in their category, or above the
topic list for the destination category where it will end up.

* When the shared draft is ready, it can be published to the
appropriate category by clicking a button on the topic view.

* When published, Drafts change their timestamps to the current
time, and any edits to the original post are removed.
This commit is contained in:
Robin Ward
2018-03-13 15:59:12 -04:00
parent dcbd9635f4
commit b9abd7dc9e
59 changed files with 851 additions and 260 deletions

View File

@@ -91,6 +91,22 @@ QUnit.test('replying to post - reply_as_new_topic', assert => {
});
});
QUnit.test('shared draft', assert => {
let composerActions = selectKit('.composer-actions');
visit("/");
click('#create-topic');
andThen(() => {
composerActions.expand().selectRowByValue('shared_draft');
});
andThen(() => {
assert.equal(
find('#reply-control .btn-primary.create .d-button-label').text(),
I18n.t('composer.create_shared_draft')
);
assert.ok(find('#reply-control.composing-shared-draft').length === 1);
});
});
QUnit.test('interactions', assert => {
const composerActions = selectKit('.composer-actions');
@@ -137,7 +153,7 @@ QUnit.test('interactions', assert => {
assert.equal(composerActions.rowByIndex(0).value(), 'reply_to_post');
assert.equal(composerActions.rowByIndex(1).value(), 'reply_as_private_message');
assert.equal(composerActions.rowByIndex(2).value(), 'reply_to_topic');
assert.equal(composerActions.rowByIndex(3).value(), undefined);
assert.equal(composerActions.rowByIndex(3).value(), 'shared_draft');
});
composerActions.selectRowByValue('reply_as_private_message').expand();

View File

@@ -0,0 +1,19 @@
import { acceptance } from "helpers/qunit-helpers";
acceptance("Shared Drafts", { loggedIn: true });
QUnit.test('Viewing', assert => {
visit("/t/some-topic/9");
andThen(() => {
assert.ok(find('.shared-draft-controls').length === 1);
let categoryChooser = selectKit('.shared-draft-controls .category-chooser');
assert.equal(categoryChooser.header().value(), '3');
});
click('.publish-shared-draft');
click('.bootbox .btn-primary');
andThen(() => {
assert.ok(find('.shared-draft-controls').length === 0);
});
});

View File

@@ -6,6 +6,7 @@ QUnit.test("Enter a Topic", assert => {
andThen(() => {
assert.ok(exists("#topic"), "The topic was rendered");
assert.ok(exists("#topic .cooked"), "The topic has cooked posts");
assert.ok(find('.shared-draft-notice').length === 0, "no shared draft unless there's a dest category id");
});
});
@@ -38,4 +39,4 @@ QUnit.test("Enter with 500 errors", assert => {
assert.ok(!exists("#topic"), "The topic was not rendered");
assert.ok(exists(".topic-error"), "An error message is displayed");
});
});
});

View File

@@ -3,6 +3,7 @@ export default {
"site":{
"default_archetype":"regular",
"disabled_plugins":[],
"shared_drafts_category_id":24,
"notification_types":{
"mentioned":1,
"replied":2,
@@ -171,17 +172,16 @@ export default {
},
{
"id":24,
"name":"sso",
"name":"Shared Drafts",
"color":"92278F",
"text_color":"FFFFFF",
"slug":"sso",
"slug":"shared-drafts",
"topic_count":13,
"post_count":53,
"description":"Only include actual maintained SSO (single sign on) implementations in this category. See the <a href=\"https://meta.discourse.org/t/official-single-sign-on-for-discourse/13045\">official documentation on Discourse's SSO support</a>.",
"topic_url":"/t/about-the-sso-category/13110",
"read_restricted":false,
"description":"An area for staff members to post shared drafts",
"topic_url":"/t/about-the-shared-drafts-category/13110",
"read_restricted":true,
"permission":1,
"parent_category_id":5,
"notification_level":null,
"logo_url":null,
"background_url":null

File diff suppressed because one or more lines are too long

View File

@@ -151,6 +151,7 @@ export default function() {
this.delete('/t/:id', success);
this.put('/t/:id/recover', success);
this.put('/t/:id/publish', success);
this.get("/404-body", () => {
return [200, {"Content-Type": "text/html"}, "<div class='page-not-found'>not found</div>"];