mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2025-03-23 19:30:34 -04:00
feat: simplify user guiding triggers
- Change exposed handler names to correspond to performed action - Simplify method of picking random survey on interaction with Editor - Move GUI useEffect hook to WWW in IntlGUIWithProjectHandler - Remove onClick property from ComposeComment component
This commit is contained in:
parent
d97d3143e0
commit
6fb0e3491d
7 changed files with 111 additions and 146 deletions
7
package-lock.json
generated
7
package-lock.json
generated
|
@ -80,6 +80,7 @@
|
|||
"lodash.merge": "4.6.2",
|
||||
"lodash.mergewith": "4.6.2",
|
||||
"lodash.omit": "3.1.0",
|
||||
"lodash.sample": "4.2.1",
|
||||
"lodash.uniqby": "4.7.0",
|
||||
"mini-css-extract-plugin": "1.6.2",
|
||||
"minilog": "2.1.0",
|
||||
|
@ -17081,6 +17082,12 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.sample": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.sample/-/lodash.sample-4.2.1.tgz",
|
||||
"integrity": "sha512-odCZufa8jYDBZQ+JOSePWRs+iApPdvIp3qAiKc9F22RdSCMLuUu60Jvgs2M6qMisKAeBZoumAkqDiGr9HDym/Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.throttle": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
||||
|
|
|
@ -116,6 +116,7 @@
|
|||
"lodash.mergewith": "4.6.2",
|
||||
"lodash.omit": "3.1.0",
|
||||
"lodash.uniqby": "4.7.0",
|
||||
"lodash.sample": "4.2.1",
|
||||
"mini-css-extract-plugin": "1.6.2",
|
||||
"minilog": "2.1.0",
|
||||
"pako": "0.2.8",
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
const api = require('./api');
|
||||
const sample = require('lodash.sample');
|
||||
|
||||
const USER_GUIDING_ID = process.env.USER_GUIDING_ID;
|
||||
const SCRIPT_ID = 'UserGuiding';
|
||||
const AUTONOMY_SURVEY_ID = 3048;
|
||||
const RELATIONSHIP_SURVEY_ID = 3049;
|
||||
const JOY_SURVEY_ID = 3050;
|
||||
const COMPETENCE_SURVEY_ID = 3045;
|
||||
const EDITOR_INTERACTION_SURVEY_IDS = [COMPETENCE_SURVEY_ID, JOY_SURVEY_ID];
|
||||
|
||||
const CONDITIONS = {condition_list: [
|
||||
'IsLoggedIn',
|
||||
|
@ -9,78 +14,58 @@ const CONDITIONS = {condition_list: [
|
|||
'NotMuted'
|
||||
]};
|
||||
|
||||
const getUserGuidingSnippet = () => (
|
||||
`
|
||||
(function(g, u, i, d, e, s) {
|
||||
g[e] = g[e] || [];
|
||||
var f = u.getElementsByTagName(i)[0];
|
||||
var k = u.createElement(i);
|
||||
k.async = true;
|
||||
k.src = 'https://static.userguiding.com/media/user-guiding-' + s + '-embedded.js';
|
||||
f.parentNode.insertBefore(k, f);
|
||||
if (g[d]) return;
|
||||
var ug = g[d] = {
|
||||
q: []
|
||||
const USER_GUIDING_SNIPPET = `
|
||||
(function(g, u, i, d, e, s) {
|
||||
g[e] = g[e] || [];
|
||||
var f = u.getElementsByTagName(i)[0];
|
||||
var k = u.createElement(i);
|
||||
k.async = true;
|
||||
k.src = 'https://static.userguiding.com/media/user-guiding-' + s + '-embedded.js';
|
||||
f.parentNode.insertBefore(k, f);
|
||||
if (g[d]) return;
|
||||
var ug = g[d] = {
|
||||
q: []
|
||||
};
|
||||
ug.c = function(n) {
|
||||
return function() {
|
||||
ug.q.push([n, arguments])
|
||||
};
|
||||
ug.c = function(n) {
|
||||
return function() {
|
||||
ug.q.push([n, arguments])
|
||||
};
|
||||
};
|
||||
var m = ['previewGuide', 'finishPreview', 'track', 'identify', 'hideChecklist', 'launchChecklist'];
|
||||
for (var j = 0; j < m.length; j += 1) {
|
||||
ug[m[j]] = ug.c(m[j]);
|
||||
}
|
||||
})(window, document, 'script', 'userGuiding', 'userGuidingLayer', '${USER_GUIDING_ID}');
|
||||
`
|
||||
);
|
||||
|
||||
const identifyUser = userId => {
|
||||
window.userGuiding.identify(userId.toString());
|
||||
};
|
||||
|
||||
const launchSurvey = surveyId => {
|
||||
window.userGuiding.launchSurvey(surveyId);
|
||||
};
|
||||
|
||||
const probabilityPicker = data => {
|
||||
let generatedValue = Math.random();
|
||||
|
||||
for (const tmp of data) {
|
||||
if (tmp.probability < generatedValue) {
|
||||
generatedValue -= tmp.probability;
|
||||
} else {
|
||||
return tmp.prompt;
|
||||
};
|
||||
var m = ['previewGuide', 'finishPreview', 'track', 'identify', 'hideChecklist', 'launchChecklist'];
|
||||
for (var j = 0; j < m.length; j += 1) {
|
||||
ug[m[j]] = ug.c(m[j]);
|
||||
}
|
||||
}
|
||||
};
|
||||
})(window, document, 'script', 'userGuiding', 'userGuidingLayer', '${USER_GUIDING_ID}');
|
||||
`;
|
||||
|
||||
const activateUserGuiding = (userId, callback) => {
|
||||
if (USER_GUIDING_ID && !document.getElementById(SCRIPT_ID)) {
|
||||
const userGuidingScript = document.createElement('script');
|
||||
userGuidingScript.id = SCRIPT_ID;
|
||||
userGuidingScript.innerHTML = getUserGuidingSnippet();
|
||||
document.head.insertBefore(userGuidingScript, document.head.firstChild);
|
||||
|
||||
window.userGuidingSettings = {
|
||||
disablePageViewAutoCapture: true
|
||||
};
|
||||
|
||||
window.userGuidingLayer.push({
|
||||
event: 'onload',
|
||||
fn: () => identifyUser(userId)
|
||||
});
|
||||
|
||||
window.userGuidingLayer.push({
|
||||
event: 'onIdentificationComplete',
|
||||
fn: callback
|
||||
});
|
||||
} else if (window.userGuiding) {
|
||||
if (window.userGuiding) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
const userGuidingScript = document.createElement('script');
|
||||
userGuidingScript.innerHTML = USER_GUIDING_SNIPPET;
|
||||
document.head.insertBefore(userGuidingScript, document.head.firstChild);
|
||||
|
||||
window.userGuidingSettings = {disablePageViewAutoCapture: true};
|
||||
|
||||
window.userGuidingLayer.push({
|
||||
event: 'onload',
|
||||
fn: () => window.userGuiding.identify(userId.toString())
|
||||
});
|
||||
|
||||
window.userGuidingLayer.push({
|
||||
event: 'onIdentificationComplete',
|
||||
fn: callback
|
||||
});
|
||||
};
|
||||
|
||||
const displayUserGuiding = (userId, permissions, guideId, callback) => (
|
||||
const attemptDisplayUserGuidingSurvey = (userId, permissions, guideId, callback) => {
|
||||
if (!USER_GUIDING_ID || !process.env.SORTING_HAT_HOST) {
|
||||
return;
|
||||
}
|
||||
|
||||
api({
|
||||
uri: '/user_guiding',
|
||||
method: 'GET',
|
||||
|
@ -97,66 +82,43 @@ const displayUserGuiding = (userId, permissions, guideId, callback) => (
|
|||
return;
|
||||
}
|
||||
|
||||
if (body?.result === "true") {
|
||||
if (body?.result === 'true') {
|
||||
activateUserGuiding(userId, callback);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const loadCompetenceSurvey = (userId, permissions) => {
|
||||
const COMPETENCE_SURVEY_ID = 3045;
|
||||
|
||||
displayUserGuiding(
|
||||
userId,
|
||||
permissions,
|
||||
COMPETENCE_SURVEY_ID,
|
||||
() => launchSurvey(COMPETENCE_SURVEY_ID)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const loadAutonomySurvey = (userId, permissions) => {
|
||||
const AUTONOMY_SURVEY_ID = 3048;
|
||||
|
||||
displayUserGuiding(
|
||||
const onCommented = (userId, permissions) => {
|
||||
attemptDisplayUserGuidingSurvey(
|
||||
userId,
|
||||
permissions,
|
||||
AUTONOMY_SURVEY_ID,
|
||||
() => launchSurvey(AUTONOMY_SURVEY_ID)
|
||||
() => window.userGuiding.launchSurvey(AUTONOMY_SURVEY_ID)
|
||||
);
|
||||
};
|
||||
|
||||
const loadRelationshipsSurvey = (userId, permissions) => {
|
||||
const RELATIONSHIP_SURVEY_ID = 3049;
|
||||
|
||||
displayUserGuiding(
|
||||
const onProjectShared = (userId, permissions) => {
|
||||
attemptDisplayUserGuidingSurvey(
|
||||
userId,
|
||||
permissions,
|
||||
RELATIONSHIP_SURVEY_ID,
|
||||
() => launchSurvey(RELATIONSHIP_SURVEY_ID)
|
||||
() => window.userGuiding.launchSurvey(RELATIONSHIP_SURVEY_ID)
|
||||
);
|
||||
};
|
||||
|
||||
const loadJoySurvey = (userId, permissions) => {
|
||||
const JOY_SURVEY_ID = 3050;
|
||||
const onProjectLoaded = (userId, permissions) => {
|
||||
const surveyId = sample(EDITOR_INTERACTION_SURVEY_IDS);
|
||||
|
||||
displayUserGuiding(
|
||||
attemptDisplayUserGuidingSurvey(
|
||||
userId,
|
||||
permissions,
|
||||
JOY_SURVEY_ID,
|
||||
() => launchSurvey(JOY_SURVEY_ID)
|
||||
surveyId,
|
||||
() => window.userGuiding.launchSurvey(surveyId)
|
||||
);
|
||||
};
|
||||
|
||||
const loadRandomPrompt = (userId, permissions, data) => {
|
||||
const prompt = probabilityPicker(data);
|
||||
|
||||
prompt(userId, permissions);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
loadCompetenceSurvey,
|
||||
loadAutonomySurvey,
|
||||
loadRelationshipsSurvey,
|
||||
loadJoySurvey,
|
||||
loadRandomPrompt
|
||||
onProjectLoaded,
|
||||
onCommented,
|
||||
onProjectShared
|
||||
};
|
||||
|
|
|
@ -360,7 +360,6 @@ class ComposeComment extends React.Component {
|
|||
type="textarea"
|
||||
value={this.state.message}
|
||||
onInput={this.handleInput}
|
||||
onClick={this.props.onClick}
|
||||
autoFocus={this.props.isReply}
|
||||
/>
|
||||
<FlexRow className="compose-bottom-row">
|
||||
|
@ -438,7 +437,6 @@ ComposeComment.propTypes = {
|
|||
}),
|
||||
onAddComment: PropTypes.func,
|
||||
onCancel: PropTypes.func,
|
||||
onClick: PropTypes.func,
|
||||
parentId: PropTypes.number,
|
||||
postURI: PropTypes.string,
|
||||
user: PropTypes.shape({
|
||||
|
|
|
@ -34,7 +34,7 @@ const thumbnailUrl = require('../../lib/user-thumbnail');
|
|||
const FormsyProjectUpdater = require('./formsy-project-updater.jsx');
|
||||
const EmailConfirmationModal = require('../../components/modal/email-confirmation/modal.jsx');
|
||||
const EmailConfirmationBanner = require('../../components/dropdown-banner/email-confirmation/banner.jsx');
|
||||
const {loadAutonomySurvey} = require('../../lib/user-guiding.js');
|
||||
const {onCommented} = require('../../lib/user-guiding.js');
|
||||
|
||||
const projectShape = require('./projectshape.jsx').projectShape;
|
||||
require('./preview.scss');
|
||||
|
@ -147,7 +147,7 @@ const PreviewPresentation = ({
|
|||
userOwnsProject,
|
||||
visibilityInfo
|
||||
}) => {
|
||||
const [interactionWithComment, setInteractionWithComment] = useState(false);
|
||||
const [hasSubmittedComment, setHasSubmittedComment] = useState(false);
|
||||
const shareDate = ((projectInfo.history && projectInfo.history.shared)) ? projectInfo.history.shared : '';
|
||||
const revisedDate = ((projectInfo.history && projectInfo.history.modified)) ? projectInfo.history.modified : '';
|
||||
const showInstructions = editable || projectInfo.instructions ||
|
||||
|
@ -221,13 +221,14 @@ const PreviewPresentation = ({
|
|||
</FlexRow>
|
||||
);
|
||||
|
||||
const onCommentClick = useCallback(() => {
|
||||
if (!interactionWithComment && user) {
|
||||
setInteractionWithComment(!interactionWithComment);
|
||||
loadAutonomySurvey(user.id, permissions);
|
||||
const onAddCommentWrapper = useCallback(body => {
|
||||
onAddComment(body);
|
||||
if (!hasSubmittedComment && user) {
|
||||
setHasSubmittedComment(true);
|
||||
onCommented(user.id, permissions);
|
||||
}
|
||||
}, [interactionWithComment, user]);
|
||||
|
||||
}, [hasSubmittedComment, user]);
|
||||
|
||||
return (
|
||||
<div className="preview">
|
||||
{showEmailConfirmationModal && <EmailConfirmationModal
|
||||
|
@ -623,8 +624,7 @@ const PreviewPresentation = ({
|
|||
isLoggedIn ? (
|
||||
isShared && <ComposeComment
|
||||
postURI={`/proxy/comments/project/${projectId}`}
|
||||
onAddComment={onAddComment}
|
||||
onClick={onCommentClick}
|
||||
onAddComment={onAddCommentWrapper}
|
||||
/>
|
||||
) : (
|
||||
/* TODO add box for signing in to leave a comment */
|
||||
|
@ -816,15 +816,7 @@ PreviewPresentation.propTypes = {
|
|||
singleCommentId: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]),
|
||||
socialOpen: PropTypes.bool,
|
||||
user: PropTypes.shape({
|
||||
id: PropTypes.number,
|
||||
banned: PropTypes.bool,
|
||||
vpn_required: PropTypes.bool,
|
||||
username: PropTypes.string,
|
||||
token: PropTypes.string,
|
||||
thumbnailUrl: PropTypes.string,
|
||||
dateJoined: PropTypes.string,
|
||||
email: PropTypes.string,
|
||||
classroomId: PropTypes.string
|
||||
id: PropTypes.number
|
||||
}),
|
||||
userOwnsProject: PropTypes.bool,
|
||||
visibilityInfo: PropTypes.shape({
|
||||
|
|
|
@ -26,10 +26,8 @@ const CanceledDeletionModal = require('../../components/login/canceled-deletion-
|
|||
const NotAvailable = require('../../components/not-available/not-available.jsx');
|
||||
const Meta = require('./meta.jsx');
|
||||
const {
|
||||
loadRelationshipsSurvey,
|
||||
loadCompetenceSurvey,
|
||||
loadJoySurvey,
|
||||
loadRandomPrompt
|
||||
onProjectShared,
|
||||
onProjectLoaded
|
||||
} = require('../../lib/user-guiding.js');
|
||||
|
||||
const sessionActions = require('../../redux/session.js');
|
||||
|
@ -46,6 +44,25 @@ const IntlGUI = injectIntl(GUI.default);
|
|||
const localStorageAvailable = 'localStorage' in window && window.localStorage !== null;
|
||||
|
||||
const xhr = require('xhr');
|
||||
const {useEffect} = require('react');
|
||||
|
||||
const IntlGUIWithProjectHandler = ({user, permissions, ...props}) => {
|
||||
useEffect(() => {
|
||||
if (props.projectId && props.projectId !== '0') {
|
||||
onProjectLoaded(user.id, permissions);
|
||||
}
|
||||
}, [props.projectId, user.id, permissions]);
|
||||
|
||||
return <IntlGUI {...props} />;
|
||||
};
|
||||
|
||||
IntlGUIWithProjectHandler.propTypes = {
|
||||
...GUI.propTypes,
|
||||
user: PropTypes.shape({
|
||||
id: PropTypes.number
|
||||
}),
|
||||
permissions: PropTypes.object
|
||||
};
|
||||
|
||||
class Preview extends React.Component {
|
||||
constructor (props) {
|
||||
|
@ -89,7 +106,6 @@ class Preview extends React.Component {
|
|||
'handleUpdateProjectId',
|
||||
'handleUpdateProjectTitle',
|
||||
'handleToggleComments',
|
||||
'handleLoadRandomPrompt',
|
||||
'initCounts',
|
||||
'pushHistory',
|
||||
'renderLogin',
|
||||
|
@ -634,7 +650,7 @@ class Preview extends React.Component {
|
|||
justRemixed: false,
|
||||
justShared: true
|
||||
});
|
||||
loadRelationshipsSurvey(this.props.user.id, this.props.permissions);
|
||||
onProjectShared(this.props.user.id, this.props.permissions);
|
||||
}
|
||||
handleShareAttempt () {
|
||||
this.setState({
|
||||
|
@ -702,18 +718,6 @@ class Preview extends React.Component {
|
|||
this.props.user.token
|
||||
);
|
||||
}
|
||||
handleLoadRandomPrompt () {
|
||||
loadRandomPrompt(this.props.user.id, this.props.permissions, [
|
||||
{
|
||||
prompt: loadCompetenceSurvey,
|
||||
probability: 0.5
|
||||
},
|
||||
{
|
||||
prompt: loadJoySurvey,
|
||||
probability: 0.5
|
||||
}
|
||||
]);
|
||||
}
|
||||
initCounts (favorites, loves) {
|
||||
this.setState({
|
||||
favoriteCount: favorites,
|
||||
|
@ -863,7 +867,7 @@ class Preview extends React.Component {
|
|||
</Page> :
|
||||
<React.Fragment>
|
||||
{showGUI && (
|
||||
<IntlGUI
|
||||
<IntlGUIWithProjectHandler
|
||||
assetHost={this.props.assetHost}
|
||||
authorId={this.props.authorId}
|
||||
authorThumbnailUrl={this.props.authorThumbnailUrl}
|
||||
|
@ -901,7 +905,8 @@ class Preview extends React.Component {
|
|||
onUpdateProjectId={this.handleUpdateProjectId}
|
||||
onUpdateProjectThumbnail={this.props.handleUpdateProjectThumbnail}
|
||||
onUpdateProjectTitle={this.handleUpdateProjectTitle}
|
||||
onLoadRandomPrompt={this.handleLoadRandomPrompt}
|
||||
user={this.props.user}
|
||||
permissions={this.props.permissions}
|
||||
/>
|
||||
)}
|
||||
{this.props.registrationOpen && (
|
||||
|
|
|
@ -281,7 +281,7 @@ module.exports = {
|
|||
'process.env.GTM_ENV_AUTH': `"${process.env.GTM_ENV_AUTH || ''}"`,
|
||||
'process.env.GTM_ID': process.env.GTM_ID ? `"${process.env.GTM_ID}"` : null,
|
||||
'process.env.USER_GUIDING_ID': `"${process.env.USER_GUIDING_ID || ''}"`,
|
||||
'process.env.SORTING_HAT_HOST': `"${process.env.SORTING_HAT_HOST || 'http://127.0.0.1:7676'}"`
|
||||
'process.env.SORTING_HAT_HOST': `"${process.env.SORTING_HAT_HOST || ''}"`
|
||||
})
|
||||
])
|
||||
.concat(process.env.ANALYZE_BUNDLE === 'true' ? [
|
||||
|
|
Loading…
Add table
Reference in a new issue