* [CORL-863] Allow streams to be converted/configured to Q&A (#2809)

* Create preliminary schema changes for Q&A

Adds a mode and expert User onto the StorySettings.
Adds a mode selection drop down on a story's
Configure tab.

CORL-863

* Allow multiple experts, remove form elements from search

Makes the previous expert user on a Q&A story now
an array of users who can be assigned.

Converts the previous form based search that was
pulled from the admin community area into a set
of events built on callbacks.

CORL-863

* Create addExpertToStory mutation

CORL-863

* Create removeExpertFromStory mutation

CORL-863

* Conditionally show the the expert selection options

CORL-863

* Create a dropdown search control for Q&A experts

CORL-863

* Fixing up tests to match new QA stream options

Adds a few localization fixes to make sure tests
pass.
Updates existing snapshots.

CORL-863

* Add load more button to expert search list

CORL-863

* Update experts query to match react upgrades

CORL-863

* Move the Q&A config to its own section under stream config

Create enable and disable Q&A mutations/button toggle.

CORL-863

* Fix alignment and layout of expert list items

CORL-863

* Define translations and update tests

CORL-863

* Use official copy for Q&A config

CORL-863

* [CORL-856] Show expert badge on comments (#2829)

* Create preliminary schema changes for Q&A

Adds a mode and expert User onto the StorySettings.
Adds a mode selection drop down on a story's
Configure tab.

CORL-863

* Allow multiple experts, remove form elements from search

Makes the previous expert user on a Q&A story now
an array of users who can be assigned.

Converts the previous form based search that was
pulled from the admin community area into a set
of events built on callbacks.

CORL-863

* Create addExpertToStory mutation

CORL-863

* Create removeExpertFromStory mutation

CORL-863

* Conditionally show the the expert selection options

CORL-863

* Create a dropdown search control for Q&A experts

CORL-863

* Fixing up tests to match new QA stream options

Adds a few localization fixes to make sure tests
pass.
Updates existing snapshots.

CORL-863

* Add load more button to expert search list

CORL-863

* Update experts query to match react upgrades

CORL-863

* Move the Q&A config to its own section under stream config

Create enable and disable Q&A mutations/button toggle.

CORL-863

* Fix alignment and layout of expert list items

CORL-863

* Define translations and update tests

CORL-863

* Use official copy for Q&A config

CORL-863

* Show expert badges on comments when Q&A is enabled

CORL-856

* Update mutation responses and tests due to added expert fields

CORL-856

* Use EXPERT user tags to denote expert users

Removes the need for viewerIsExpert and
authorIsExpert loader/resolvers on Stories
and Comments respectively.

CORL-856

* [CORL-879] Add an unanswered tab to stream when in Q&A mode (#2838)

* Create preliminary schema changes for Q&A

Adds a mode and expert User onto the StorySettings.
Adds a mode selection drop down on a story's
Configure tab.

CORL-863

* Allow multiple experts, remove form elements from search

Makes the previous expert user on a Q&A story now
an array of users who can be assigned.

Converts the previous form based search that was
pulled from the admin community area into a set
of events built on callbacks.

CORL-863

* Create addExpertToStory mutation

CORL-863

* Create removeExpertFromStory mutation

CORL-863

* Conditionally show the the expert selection options

CORL-863

* Create a dropdown search control for Q&A experts

CORL-863

* Fixing up tests to match new QA stream options

Adds a few localization fixes to make sure tests
pass.
Updates existing snapshots.

CORL-863

* Add load more button to expert search list

CORL-863

* Update experts query to match react upgrades

CORL-863

* Move the Q&A config to its own section under stream config

Create enable and disable Q&A mutations/button toggle.

CORL-863

* Fix alignment and layout of expert list items

CORL-863

* Define translations and update tests

CORL-863

* Use official copy for Q&A config

CORL-863

* Show expert badges on comments when Q&A is enabled

CORL-856

* Update mutation responses and tests due to added expert fields

CORL-856

* Use EXPERT user tags to denote expert users

Removes the need for viewerIsExpert and
authorIsExpert loader/resolvers on Stories
and Comments respectively.

CORL-856

* Show an unanswered comment stream when Q&A is enabled

CORL-879

* Do not visually show the unanswered tag

CORL-879

* [CORL-859] Convert Featured stream into Answered for Q&A (#2842)

* Create preliminary schema changes for Q&A

Adds a mode and expert User onto the StorySettings.
Adds a mode selection drop down on a story's
Configure tab.

CORL-863

* Allow multiple experts, remove form elements from search

Makes the previous expert user on a Q&A story now
an array of users who can be assigned.

Converts the previous form based search that was
pulled from the admin community area into a set
of events built on callbacks.

CORL-863

* Create addExpertToStory mutation

CORL-863

* Create removeExpertFromStory mutation

CORL-863

* Conditionally show the the expert selection options

CORL-863

* Create a dropdown search control for Q&A experts

CORL-863

* Fixing up tests to match new QA stream options

Adds a few localization fixes to make sure tests
pass.
Updates existing snapshots.

CORL-863

* Add load more button to expert search list

CORL-863

* Update experts query to match react upgrades

CORL-863

* Move the Q&A config to its own section under stream config

Create enable and disable Q&A mutations/button toggle.

CORL-863

* Fix alignment and layout of expert list items

CORL-863

* Define translations and update tests

CORL-863

* Use official copy for Q&A config

CORL-863

* Show expert badges on comments when Q&A is enabled

CORL-856

* Update mutation responses and tests due to added expert fields

CORL-856

* Use EXPERT user tags to denote expert users

Removes the need for viewerIsExpert and
authorIsExpert loader/resolvers on Stories
and Comments respectively.

CORL-856

* Show an unanswered comment stream when Q&A is enabled

CORL-879

* Create preliminary schema changes for Q&A

Adds a mode and expert User onto the StorySettings.
Adds a mode selection drop down on a story's
Configure tab.

CORL-863

* Do not visually show the unanswered tag

CORL-879

* Allow multiple experts, remove form elements from search

Makes the previous expert user on a Q&A story now
an array of users who can be assigned.

Converts the previous form based search that was
pulled from the admin community area into a set
of events built on callbacks.

CORL-863

* Create addExpertToStory mutation

CORL-863

* Create removeExpertFromStory mutation

CORL-863

* Create a dropdown search control for Q&A experts

CORL-863

* Fixing up tests to match new QA stream options

Adds a few localization fixes to make sure tests
pass.
Updates existing snapshots.

CORL-863

* Add load more button to expert search list

CORL-863

* Update experts query to match react upgrades

CORL-863

* Move the Q&A config to its own section under stream config

Create enable and disable Q&A mutations/button toggle.

CORL-863

* Fix alignment and layout of expert list items

CORL-863

* Define translations and update tests

CORL-863

* Show expert badges on comments when Q&A is enabled

CORL-856

* Use official copy for Q&A config

CORL-863

* Update mutation responses and tests due to added expert fields

CORL-856

* Use EXPERT user tags to denote expert users

Removes the need for viewerIsExpert and
authorIsExpert loader/resolvers on Stories
and Comments respectively.

CORL-856

* Create the answered stream for Q&A

CORL-859

* Sort the Q&A on Most Voted by default

CORL-859

* Fix type mismatch between post comment form and fragments

CORL-859

* Adding localizations for Q&A tags

* Hide feature flags in Q&A streams

* Allow experts to clear answered questions

Can click a button that shows up in the unanswered
tab under answered questions to refresh the stream,
clearing the answered questions from that tab.

* Show arrow upvote icon when in Q&A mode

Also localized the upvote text so it can
be translated.

* Hide mod/report buttons on answered questions

* Remove unnecessary fragment container

* Remove errant debug console log

* Make story mode required on story settings

* Make remove button outlined, not filled

* Further schema changes around Q&A and experts

Rename add/remove story expert to removeStoryExpert
and addStoryExpert naming.

Replace enableQA and disableQA mutators with single
updateStoryMode mutator.

* Remove story mode from UpdateStorySettings

* Replace inline string val's with enum

* add dependencies to useEffect

* docs cleanup around tags.type index check

* Approve a question when it is answered in Q&A

Approves using the author's id as the moderator

* Add comment around use of TAG on comments edge

* Use tagFilter instead of $elemMatch to filter by tags

* Improve responsive styles for expert list items

* Update copy to "Done" from "Remove answered questions"

* Text styling for no users found text

Styles the expert search list to have proper
text styling when no users are found for the
search keyword.

* Remove duplicate checks around story experts

Not necessary as Mongo does this for us.

* Fix a missed "sort imports" during rebase

* Refactor Q&A moderation phases for clarity

Simplify logic and update comments.
Rename: "answered" -> "tagExpertAnswers"
Rename: "unanswered" -> "tagUnansweredQuestions"

* Remove username & email from add expert mutation

* Format expert list emails with Localized

* Break out no comments logic into fragment

* Remove ref handling from expert search field

Use value assignment on TextField instead.

* Replace Box with Flex and CSS

* Show Q&A tooltip on Answered tab

Co-authored-by: Kim Gardner <kgardnr@gmail.com>
This commit is contained in:
Nick Funk
2020-02-25 20:10:25 -05:00
committed by GitHub
co-authored by Kim Gardner
parent 184f145c4a
commit 1a3401710f
100 changed files with 3761 additions and 114 deletions
+4 -6
View File
@@ -926,12 +926,9 @@ export async function retrieveStoryCommentTagCounts(
// Build up the $match query.
const $match: FilterQuery<Comment> = {
tenantID,
// We're filtering only for featured comments for now because that's all
// that is returned by the tag counts at the moment. If we ever extend this
// we should switch this out to something like
// `"tags.type": { $exists: true }` to ensure that we are using the
// specified index.
"tags.type": GQLTAG.FEATURED,
// ensure we are using the tags.type index, this
// currently includes FEATURED and UNANSWERED tags
"tags.type": { $exists: true },
// Only show published comment's tag counts.
status: { $in: PUBLISHED_STATUSES },
};
@@ -986,6 +983,7 @@ export async function retrieveStoryCommentTagCounts(
// missing/extra tags here.
{
[GQLTAG.FEATURED]: 0,
[GQLTAG.UNANSWERED]: 0,
}
);
});
+120 -1
View File
@@ -6,6 +6,7 @@ import { dotize } from "coral-common/utils/dotize";
import {
DuplicateStoryIDError,
DuplicateStoryURLError,
StoryNotFoundError,
} from "coral-server/errors";
import {
Connection,
@@ -18,6 +19,7 @@ import { TenantResource } from "coral-server/models/tenant";
import { stories as collection } from "coral-server/services/mongodb/collections";
import {
GQLSTORY_MODE,
GQLStoryMetadata,
GQLStorySettings,
} from "coral-server/graph/schema/__generated__/types";
@@ -30,8 +32,26 @@ import {
export * from "./helpers";
export interface StreamModeSettings {
/**
* mode is whether the story stream is in commenting or Q&A mode.
* This will determine the appearance of the stream and how it functions.
* This is an optional parameter and if unset, defaults to commenting.
*/
mode?: GQLSTORY_MODE;
/**
* experts are used during Q&A mode to assign users to answer questions
* on a Q&A stream. It is an optional parameter and is only used when
* the story stream is in Q&A mode.
*/
expertIDs?: string[];
}
export type StorySettings = DeepPartial<
Pick<GQLStorySettings, "messageBox"> & GlobalModerationSettings
StreamModeSettings &
GlobalModerationSettings &
Pick<GQLStorySettings, "messageBox" | "mode" | "experts">
>;
export type StoryMetadata = GQLStoryMetadata;
@@ -544,3 +564,102 @@ export const updateStoryCounts = (
id: string,
commentCounts: FirstDeepPartial<RelatedCommentCounts>
) => updateRelatedCommentCounts(collection(mongo), tenantID, id, commentCounts);
export async function addExpert(
mongo: Db,
tenantID: string,
storyID: string,
userID: string
) {
const story = await collection(mongo).findOne({ tenantID, id: storyID });
if (!story) {
throw new StoryNotFoundError(storyID);
}
const result = await collection(mongo).findOneAndUpdate(
{
tenantID,
id: storyID,
},
{
$addToSet: {
"settings.expertIDs": userID,
},
},
{
returnOriginal: false,
}
);
if (!result.ok) {
throw new Error("unable to add expert to story");
}
return result.value || null;
}
export async function removeExpert(
mongo: Db,
tenantID: string,
storyID: string,
userID: string
) {
const story = await collection(mongo).findOne({ tenantID, id: storyID });
if (!story) {
throw new StoryNotFoundError(storyID);
}
const result = await collection(mongo).findOneAndUpdate(
{
tenantID,
id: storyID,
},
{
$pull: {
"settings.expertIDs": userID,
},
},
{
returnOriginal: false,
}
);
if (!result.ok) {
throw new Error("unable to remove expert from story");
}
return result.value || null;
}
export async function setStoryMode(
mongo: Db,
tenantID: string,
storyID: string,
mode: GQLSTORY_MODE
) {
const story = await collection(mongo).findOne({ tenantID, id: storyID });
if (!story) {
throw new StoryNotFoundError(storyID);
}
const result = await collection(mongo).findOneAndUpdate(
{
tenantID,
id: storyID,
},
{
$set: {
"settings.mode": mode,
},
},
{
returnOriginal: false,
}
);
if (!result.ok) {
throw new Error("unable to enable Q&A on story");
}
return result.value || null;
}