Skip to content

Commit ec100e2

Browse files
committed
Merge branch 'master' into development
2 parents 507300c + 30117e5 commit ec100e2

File tree

36 files changed

+296
-177
lines changed

36 files changed

+296
-177
lines changed

app/index.html

-18
Original file line numberDiff line numberDiff line change
@@ -65,24 +65,6 @@
6565
<!-- End of Quora Pixel Code -->
6666

6767
<script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async></script>
68-
<script>
69-
var OneSignal = window.OneSignal || [];
70-
OneSignal.push(function() {
71-
OneSignal.init({
72-
allowLocalhostAsSecureOrigin: true,
73-
appId: "01d75aac-5123-4145-b655-ba8d27c5dc13",
74-
});
75-
});
76-
</script>
77-
78-
<!-- <script async src="https://www.googletagmanager.com/gtag/js?id=UA-83327907-12"></script>
79-
<script>
80-
window.dataLayer = window.dataLayer || [];
81-
function gtag(){dataLayer.push(arguments);}
82-
gtag('js', new Date());
83-
84-
gtag('config', 'UA-83327907-12');
85-
</script> -->
8668

8769
<link rel="preload" href="https://dev.vdocipher.com/playerAssets/1.6.10/vdo.js" as="script">
8870
<script src="https://dev.vdocipher.com/playerAssets/1.6.10/vdo.js"></script>

app/mixins/utm-cookie-route.js

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import Mixin from '@ember/object/mixin';
2+
3+
// Modified over: https://stackoverflow.com/questions/10730362/get-cookie-by-name
4+
function getCookie(name, defaultValue = window.btoa('{}')){
5+
var pattern = RegExp(name + "=.[^;]*")
6+
var matched = document.cookie.match(pattern)
7+
if(matched){
8+
var cookie = matched[0].split('=')
9+
return cookie[1]
10+
}
11+
return defaultValue
12+
}
13+
14+
const utm_params = ['utm_campaign', 'utm_source', 'utm_medium', 'utm_term', 'utm_content', 'utm_coupon']
15+
const resetProps = utm_params.reduce((acc, key) => ({ ...acc, [key]: null }), {})
16+
const defaultQpProps = { replace: true }
17+
const queryParamsProps = utm_params.reduce((acc, key) => ({...acc, [key]: defaultQpProps}), {})
18+
19+
export default Mixin.create({
20+
queryParams: queryParamsProps,
21+
beforeModel(transition) {
22+
const qp = transition.to.queryParams
23+
const new_cbutm = Object.keys(qp).reduce((acc, key) => utm_params.includes(key) && qp[key] ? {...acc, [key]: qp[key]} : acc , {})
24+
const old_cbutm = JSON.parse(window.atob((getCookie('_cbutm'))))
25+
const _cbutm = window.btoa(JSON.stringify({
26+
...old_cbutm,
27+
...new_cbutm
28+
}))
29+
const expiry = moment().add("7", "days").toDate()
30+
document.cookie = `_cbutm=${_cbutm}; expires=${expiry}; path=/; domain=.codingblocks.com`
31+
// document.cookie = `_cbutm=${_cbutm}; expires=${expiry}; path=/; domain=test.online` // in dev uncomment this
32+
this._super(...arguments)
33+
},
34+
actions: {
35+
didTransition() {
36+
this._super(...arguments)
37+
this.controller.setProperties({
38+
...resetProps,
39+
code: null
40+
})
41+
}
42+
}
43+
})

app/pods/application/controller.js

+10
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ export default class ApplicationController extends Controller {
88
@service router
99
@service session
1010
@service layout
11+
12+
queryParams = ['utm_campaign', 'utm_source', 'utm_medium', 'utm_term', 'utm_content', 'utm_coupon' ,'code']
13+
utm_campaign = null
14+
utm_source = null
15+
utm_medium = null
16+
utm_term = null
17+
utm_content = null
18+
utm_coupon = null
19+
code = null
20+
1121
@computed ('router.currentRouteName')
1222
get isInsideAttemptRoute () {
1323
return ['attempt'].includes(this.get('router.currentRouteName').split('.')[0])

app/pods/application/route.js

+54-72
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,76 @@
1-
import Route from '@ember/routing/route';
2-
import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';
3-
import { inject as service } from '@ember/service';
4-
import { isNone } from '@ember/utils';
1+
import Route from "@ember/routing/route";
2+
import ApplicationRouteMixin from "ember-simple-auth/mixins/application-route-mixin";
3+
import UtmCookieRouteMixin from "../../mixins/utm-cookie-route"
4+
import { inject as service } from "@ember/service";
5+
import { isNone } from "@ember/utils";
56

6-
export default Route.extend(ApplicationRouteMixin, {
7+
export default Route.extend(ApplicationRouteMixin, UtmCookieRouteMixin, {
78
session: service(),
89
currentUser: service(),
9-
store: service (),
10+
store: service(),
1011
headData: service(),
12+
onesignal: service(),
1113
metrics: service(), // !important: keep this here to init trackers for all routes
1214
// routeAfterAuthentication: 'dashboard',
1315
queryParams: {
1416
code: {
15-
refreshModel: true
17+
refreshModel: true,
18+
repalce: true
1619
}
1720
},
1821
async beforeModel(transition) {
22+
this._super(...arguments)
1923
this.metrics; // !important: keep this here to init trackers for all routes
20-
if (!isNone(transition.to.queryParams.code)) {
21-
if (this.get('session.isAuthenticated')) {
22-
return ''
23-
// return this.transitionTo({ queryParams: { code: undefined } })
24-
}
25-
// we have ?code qp
26-
const { code } = transition.to.queryParams
27-
28-
return this.session.authenticate('authenticator:jwt', { identification: code, password: code, code })
29-
.then(() => this.currentUser.load())
30-
.then(user => {
31-
// if user belongs to an org, redirect to the domain
32-
if(user.get('organization')) {
33-
this.transitionTo(user.get('organization'))
34-
}
35-
})
36-
.catch(error => {
37-
if (error.err === 'USER_EMAIL_NOT_VERIFIED') {
38-
return this.transitionTo('error', {
39-
queryParams: {
40-
errorCode: 'USER_EMAIL_NOT_VERIFIED'
41-
}
42-
})
43-
}
44-
if (error.name == 'USER_LOGGED_IN_ELSEWHERE') {
45-
return this.transitionTo('login-blocker', {
46-
queryParams: {
47-
code: null,
48-
token: error.logout_token
49-
}
50-
})
51-
}
52-
});
24+
this.onesignal;
25+
if (!isNone(transition.to.queryParams.code)) {
26+
if (this.get("session.isAuthenticated")) {
27+
return "";
28+
// return this.transitionTo({ queryParams: { code: undefined } })
5329
}
54-
},
55-
model () {
56-
if (this.get('session.isAuthenticated')) {
57-
return this.currentUser.load().then (user => {
58-
try {
59-
OneSignal.getUserId ().then (userId => {
60-
if (! userId) {
61-
throw new Error ('player ID not found')
62-
}
63-
64-
const player = this.store.createRecord ('player')
65-
66-
player.set ('playerId', userId)
30+
// we have ?code qp
31+
const { code } = transition.to.queryParams;
6732

68-
return player.save ()
69-
})
70-
.then (result => console.log ('playerId set!'))
71-
.catch (error => console.error (error))
33+
return this.session
34+
.authenticate("authenticator:jwt", {
35+
identification: code,
36+
password: code,
37+
code
38+
})
39+
.then(() => this.currentUser.load())
40+
.then(user => {
41+
// if user belongs to an org, redirect to the domain
42+
if (user.get("organization")) {
43+
this.transitionTo(user.get("organization"));
44+
}
45+
})
46+
.catch(error => {
47+
if (error.err === "USER_EMAIL_NOT_VERIFIED") {
48+
return this.transitionTo("error", {
49+
queryParams: {
50+
errorCode: "USER_EMAIL_NOT_VERIFIED"
51+
}
52+
});
7253
}
73-
catch (error) {
74-
console.error(error)
54+
if (error.name == "USER_LOGGED_IN_ELSEWHERE") {
55+
return this.transitionTo("login-blocker", {
56+
queryParams: {
57+
code: null,
58+
token: error.logout_token
59+
}
60+
});
7561
}
76-
return user
7762
});
78-
}
63+
}
7964
},
80-
81-
setupController(controller, model){
82-
this._super(controller, model)
83-
controller.set('model', model)
84-
85-
// later(function(){
86-
// controller.set('code', undefined)
87-
// })
65+
model() {
66+
return this.get("session.isAuthenticated") && this.currentUser.load()
8867
},
8968
afterModel(model) {
90-
this.set('headData.title', 'Coding Blocks Online')
69+
this.set("headData.title", "Coding Blocks Online")
9170
},
9271

93-
94-
})
72+
setupController(controller, model) {
73+
this._super(controller, model);
74+
controller.set("model", model);
75+
}
76+
});

app/pods/attempt/content/lecture/controller.js

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ export default class LectureController extends Controller {
1111
@action
1212
async markProgress() {
1313
const progress = await this.content.get('progress')
14+
if (progress.status == 'DONE') // don't mark progress if already done
15+
return;
16+
1417
progress.set('status', 'DONE')
1518
this.runAttempt.incrementProperty("completedContents")
1619
progress.save()

app/pods/attempt/content/route.js

+6-9
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@ export default Route.extend({
77
api: inject(),
88
currentUser: inject(),
99
headData: inject(),
10-
async beforeModel() {
11-
const params = this.paramsFor('attempt.content')
10+
async model(params) {
1211
const section = this.store.peekRecord('section', params.sectionId)
13-
return section.get('contents')
14-
},
15-
model (params) {
16-
return this.store.peekRecord('content', params.contentId, {
17-
include: 'lecture,video,document,code_challenge,webinar',
18-
reload: true
19-
})
12+
await section.get('contents')
13+
return this.store.peekRecord('content', params.contentId, {
14+
include: 'lecture,video,document,code_challenge,webinar',
15+
reload: true
16+
})
2017
},
2118
setupController(controller) {
2219
this._super(...arguments)

app/pods/attempt/controller.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ export default class AttemptController extends Controller {
6060
}
6161

6262
@action
63-
async startTour() {
64-
const startTour = await this.productTour.preparePlayerTour(true)
65-
startTour()
63+
startTour() {
64+
this.productTour.start(true)
6665
}
6766
}

app/pods/attempt/route.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ export default Route.extend(AuthenticatedRouteMixin, {
99
router: service(),
1010
productTour: service(),
1111
async beforeModel() {
12-
const startTour = await this.productTour.preparePlayerTour()
13-
scheduleOnce('afterRender', startTour)
12+
this._super(...arguments)
13+
await this.productTour.preparePlayerTour()
14+
scheduleOnce('afterRender', () => this.productTour.start())
1415
},
1516
model(params, transition) {
1617
return this.store.findRecord('runAttempt', params.runAttemptId, { reload: true })
@@ -45,9 +46,11 @@ export default Route.extend(AuthenticatedRouteMixin, {
4546
},
4647
actions: {
4748
willTransition() {
49+
this._super(...arguments)
4850
window.setTimeout( () => jivo_init(), 5000)
4951
},
5052
didTransition() {
53+
this._super(...arguments)
5154
try {
5255
jivo_init();
5356
} catch (err) {

app/pods/classroom/timeline/index/controller.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,15 @@ export default class Overview extends Controller {
7979
}
8080

8181
@action
82-
async startTour() {
83-
const startTour = await this.productTour.prepareCourseDashboardTour(true)
84-
startTour()
82+
startTour() {
83+
this.productTour.start(true)
8584
}
8685

8786
@action
8887
log(event, course){
89-
this.metrics.trackEvent({event, course, page: 'Classroom'})
88+
this.metrics.trackEvent({
89+
action: event,
90+
category: course,
91+
})
9092
}
9193
}

app/pods/classroom/timeline/index/route.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@ export default Route.extend({
1717
},
1818
async afterModel(model) {
1919
this.set('headData.title', 'My Classroom | ' + model.get('run.course.title'))
20-
const startTour = await this.productTour.prepareCourseDashboardTour()
21-
scheduleOnce('afterRender', startTour)
20+
await this.productTour.prepareCourseDashboardTour()
21+
scheduleOnce('afterRender', () => this.productTour.start())
2222
},
2323
actions: {
24-
log(event, course){
25-
this.get('metrics').trackEvent({event, course, page: 'Classroom'})
24+
log(action, courseIdentifier){
25+
this.metrics.trackEvent({
26+
category: 'course',
27+
label: courseIdentifier,
28+
action
29+
})
2630
}
2731
}
2832
});

app/pods/classroom/timeline/index/template.hbs

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,12 @@
9696
</div>
9797
<div>
9898
{{#if showBuyNow}}
99-
<a href="/courses/{{course.identifier}}" class="button-solid button-orange mr-4" onclick={{action 'log' 'Buy now' course.identifier preventDefault=false}}>
99+
<a href="/courses/{{course.identifier}}" class="button-solid button-orange mr-4" onclick={{action 'log' 'buy_now' course.identifier preventDefault=false}}>
100100
Buy Now
101101
</a>
102102
{{/if}}
103103

104-
{{#link-to "attempt" runAttempt.id activeClass="" class="button-dashed button-orange" invokeAction=(action 'log' 'Resume' runAttempt.id preventDefault=false)}}
104+
{{#link-to "attempt" runAttempt.id activeClass="" class="button-dashed button-orange" invokeAction=(action 'log' 'resume' course.identifier preventDefault=false)}}
105105
Resume
106106
{{/link-to}}
107107
</div>

app/pods/components/accordion-head/template.hbs

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@
6868
<div class="li-right col-4">
6969
<div class="d-flex flex-column align-items-end">
7070
<div class="{{if (eq completed total) 'green'}}">{{completed}}/{{total}} Lectures Completed</div>
71-
{{#if (and deadline (not (eq completed total)))}}
71+
{{!-- {{#if (and deadline (not (eq completed total)))}}
7272
<div class="red mt-2 deadline">Due {{moment-format deadline 'DD-MMM-YY'}}</div>
73-
{{/if}}
73+
{{/if}} --}}
7474
</div>
7575
</div>
7676
{{/if}}

app/pods/components/code-challenge/code-challenge-code-editor/template.hbs

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
</div>
7979
</div>
8080

81-
{{#if lastResult}}
81+
{{#if (and lastResult (not judgeTaskGroup.isRunning))}}
8282
{{#if (and explanation showExplanation)}}
8383
<div class="border-card border-none mb-5 bg-grey-darker">
8484
<div class="font-sm bold white">

0 commit comments

Comments
 (0)