فهرست منبع

Merge branch 'sk-link-sharing-onboarding'

Shane Kilkelly 9 سال پیش
والد
کامیت
8ba9073606

+ 20 - 0
services/web/app/coffee/Features/Project/ProjectController.coffee

@@ -294,6 +294,23 @@ module.exports = ProjectController =
 					else
 					else
 						logger.log { user_id, event }, "autocompile onboarding not shown yet to this user"
 						logger.log { user_id, event }, "autocompile onboarding not shown yet to this user"
 						return cb(null, { enabled: true, showOnboarding: true })
 						return cb(null, { enabled: true, showOnboarding: true })
+			couldShowLinkSharingOnboarding: (cb) ->
+				cb = underscore.once(cb)
+				if !user_id?
+					return cb()
+				# Extract data from user's ObjectId
+				timestamp = parseInt(user_id.toString().substring(0, 8), 16)
+				userSignupDate = new Date(timestamp * 1000)
+				if userSignupDate > new Date("2017-11-10")
+					# Don't show for users who registered after it was released
+					return cb(null, false)
+				timeout = setTimeout cb, 500
+				AnalyticsManager.getLastOccurance user_id, "shown-linksharing-onboarding", (error, event) ->
+					clearTimeout timeout
+					if error? || event?
+						return cb(null, false)
+					else
+						return cb(null, true)
 		}, (err, results)->
 		}, (err, results)->
 			if err?
 			if err?
 				logger.err err:err, "error getting details for project page"
 				logger.err err:err, "error getting details for project page"
@@ -308,11 +325,13 @@ module.exports = ProjectController =
 
 
 			token = TokenAccessHandler.getRequestToken(req, project_id)
 			token = TokenAccessHandler.getRequestToken(req, project_id)
 			isTokenMember = results.isTokenMember
 			isTokenMember = results.isTokenMember
+			# Roll out token-access based on Project owner
 			enableTokenAccessUI = ProjectController._isInPercentageRollout(
 			enableTokenAccessUI = ProjectController._isInPercentageRollout(
 				'linksharing',
 				'linksharing',
 				project.owner_ref,
 				project.owner_ref,
 				0
 				0
 			)
 			)
+			showLinkSharingOnboarding = enableTokenAccessUI && results.couldShowLinkSharingOnboarding
 			AuthorizationManager.getPrivilegeLevelForProject user_id, project_id, token, (error, privilegeLevel)->
 			AuthorizationManager.getPrivilegeLevelForProject user_id, project_id, token, (error, privilegeLevel)->
 				return next(error) if error?
 				return next(error) if error?
 				if !privilegeLevel? or privilegeLevel == PrivilegeLevels.NONE
 				if !privilegeLevel? or privilegeLevel == PrivilegeLevels.NONE
@@ -364,6 +383,7 @@ module.exports = ProjectController =
 					themes: THEME_LIST
 					themes: THEME_LIST
 					maxDocLength: Settings.max_doc_length
 					maxDocLength: Settings.max_doc_length
 					enableTokenAccessUI: enableTokenAccessUI
 					enableTokenAccessUI: enableTokenAccessUI
+					showLinkSharingOnboarding: showLinkSharingOnboarding
 				timer.done()
 				timer.done()
 
 
 	_buildProjectList: (allProjects)->
 	_buildProjectList: (allProjects)->

+ 1 - 0
services/web/app/views/project/editor.pug

@@ -126,6 +126,7 @@ block requirejs
 		window.showPerUserTCNotice = #{!!showPerUserTCNotice};
 		window.showPerUserTCNotice = #{!!showPerUserTCNotice};
 		window.autoCompileEnabled = #{!!autoCompileEnabled};
 		window.autoCompileEnabled = #{!!autoCompileEnabled};
 		window.showAutoCompileOnboarding = #{!!showAutoCompileOnboarding}
 		window.showAutoCompileOnboarding = #{!!showAutoCompileOnboarding}
+		window.showLinkSharingOnboarding = #{!!showLinkSharingOnboarding}
 		window.wikiEnabled = #{!!(settings.apis.wiki && settings.apis.wiki.url)};
 		window.wikiEnabled = #{!!(settings.apis.wiki && settings.apis.wiki.url)};
 		window.enableTokenAccessUI = #{enableTokenAccessUI}
 		window.enableTokenAccessUI = #{enableTokenAccessUI}
 		window.requirejs = {
 		window.requirejs = {

+ 14 - 0
services/web/app/views/project/editor/editor.pug

@@ -108,3 +108,17 @@ div.full-size(
 			p #{translate("auto_compile_onboarding_description")}
 			p #{translate("auto_compile_onboarding_description")}
 			button.btn.btn-default.btn-block(ng-click="dismiss()")
 			button.btn.btn-default.btn-block(ng-click="dismiss()")
 				| #{translate("got_it")}
 				| #{translate("got_it")}
+
+#onboarding-linksharing.onboarding-linksharing.popover(
+	ng-controller="LinkSharingOnboardingController"
+	ng-if="permissions.admin && onboarding.linkSharing == 'unseen'"
+	ng-class="placement"
+)
+	.popover-inner
+		h3.popover-title #{translate("link_sharing")}
+		.popover-content
+			p #{translate("try_out_link_sharing")}
+			img(src="/img/onboarding/linksharing/link-sharing.png" width="100%")
+			p #{translate("try_link_sharing_description")}
+			button.btn.btn-default.btn-block(ng-click="dismiss()")
+				| #{translate("got_it")}

+ 1 - 1
services/web/app/views/project/editor/header.pug

@@ -99,7 +99,7 @@ header.toolbar.toolbar-header.toolbar-with-labels(
 			i.review-icon
 			i.review-icon
 			p.toolbar-label
 			p.toolbar-label
 				| #{translate("review")}
 				| #{translate("review")}
-		a.btn.btn-full-height(
+		a.btn.btn-full-height#shareButton(
 			href,
 			href,
 			ng-if="permissions.admin",
 			ng-if="permissions.admin",
 			ng-click="openShareProjectModal();",
 			ng-click="openShareProjectModal();",

+ 12 - 0
services/web/public/coffee/ide.coffee

@@ -14,6 +14,7 @@ define [
 	"ide/SafariScrollPatcher"
 	"ide/SafariScrollPatcher"
 	"ide/FeatureOnboardingController",
 	"ide/FeatureOnboardingController",
 	"ide/AutoCompileOnboardingController",
 	"ide/AutoCompileOnboardingController",
+	"ide/LinkSharingOnboardingController",
 	"ide/settings/index"
 	"ide/settings/index"
 	"ide/share/index"
 	"ide/share/index"
 	"ide/chat/index"
 	"ide/chat/index"
@@ -79,6 +80,7 @@ define [
 		}
 		}
 		$scope.onboarding = {
 		$scope.onboarding = {
 			autoCompile: if window.showAutoCompileOnboarding then 'unseen' else 'dismissed'
 			autoCompile: if window.showAutoCompileOnboarding then 'unseen' else 'dismissed'
+			linkSharing: if window.showLinkSharingOnboarding then 'unseen' else 'dismissed'
 		}
 		}
 		$scope.user = window.user
 		$scope.user = window.user
 		$scope.__enableTokenAccessUI = window.enableTokenAccessUI == true
 		$scope.__enableTokenAccessUI = window.enableTokenAccessUI == true
@@ -169,6 +171,16 @@ define [
 				, 200
 				, 200
 			)
 			)
 
 
+		# Count the first 'doc:opened' as a sign that the ide is loaded
+		# and broadcast a message. This is a good event to listen for
+		# if you want to wait until the ide is fully loaded and initialized
+		_loaded = false
+		$scope.$on 'doc:opened', () ->
+			if _loaded
+				return
+			$scope.$broadcast('ide:loaded')
+			_loaded = true
+
 		DARK_THEMES = [
 		DARK_THEMES = [
 			"ambiance", "chaos", "clouds_midnight", "cobalt", "idle_fingers",
 			"ambiance", "chaos", "clouds_midnight", "cobalt", "idle_fingers",
 			"merbivore", "merbivore_soft", "mono_industrial", "monokai",
 			"merbivore", "merbivore_soft", "mono_industrial", "monokai",

+ 21 - 0
services/web/public/coffee/ide/LinkSharingOnboardingController.coffee

@@ -0,0 +1,21 @@
+define [
+	"base"
+], (App) ->
+	App.controller "LinkSharingOnboardingController", ($scope, $timeout, event_tracking) ->
+
+		popover = angular.element('#onboarding-linksharing')
+		popover.hide()
+
+		$scope.dismiss = () ->
+			$scope.onboarding.linkSharing = 'dismissed'
+			event_tracking.sendMB "shown-linksharing-onboarding"
+
+		$scope.$on 'ide:loaded', () ->
+			shareBtn = angular.element('#shareButton')
+			offset = shareBtn.offset()
+			popover.show()
+			$scope.placement = 'bottom'
+			popover.css({
+				top: '' + (2) + 'px',
+				right: '' + (window.innerWidth - offset.left - (shareBtn.width() * 1.5) ) + 'px'
+			})

BIN
services/web/public/img/onboarding/linksharing/link-sharing.png


+ 39 - 0
services/web/public/stylesheets/app/editor/feature-onboarding.less

@@ -143,3 +143,42 @@ a.feat-onboard-dismiss {
 		right: -9.5px;
 		right: -9.5px;
 	}
 	}
 }
 }
+
+.onboarding-linksharing {
+	display: block;
+	top: 10px;
+	&.popover {
+		left: auto !important;
+	}
+
+	img {
+		margin-bottom: 10px;
+		border: 1px solid @gray-lighter;
+	}
+
+	&::before, &::after {
+		content: '';
+		border-width: 11px;
+		border-style: solid;
+		border-color: transparent;
+		top: 7px;
+		display: block;
+		position: absolute;
+	}
+
+	// Bottom
+	&.bottom::before {
+		border-top-width: 0;
+		border-bottom-color: rgba(0, 0, 0, .3);
+		top: -10px;
+		right: 38px;
+	}
+
+	&.bottom::after {
+		border-top-width: 0;
+		border-bottom-color: #f7f7f7;
+		top: -9.5px;
+		right: 38px;
+	}
+
+}