@internetarchive/ia-book-actions 0.1.4 → 0.1.5-alpha2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo/index.html +4 -4
- package/package.json +1 -1
- package/src/components/collapsible-action-group.js +25 -11
- package/src/components/timer-countdown.js +82 -26
- package/src/core/config/analytics-event-and-category.js +2 -1
- package/src/core/services/actions-handler/actions-handler.js +91 -55
- package/src/core/services/doc-cookies.js +23 -1
- package/src/core/services/loan-analytics.js +189 -0
- package/src/core/services/loan-token-poller.js +18 -11
- package/src/ia-book-actions.js +30 -24
- package/demo/with-bookreader.html +0 -146
package/demo/index.html
CHANGED
|
@@ -128,14 +128,14 @@
|
|
|
128
128
|
iaBookActions.modalConfig = modalConfig;
|
|
129
129
|
iaBookActions.lendingBarPostInit = lendingBarPostInit;
|
|
130
130
|
iaBookActions.tokenDelay = 2; // 2 seconds
|
|
131
|
-
iaBookActions.returnUrl = '
|
|
131
|
+
iaBookActions.returnUrl = '';
|
|
132
132
|
iaBookActions.localCache = localCache;
|
|
133
133
|
|
|
134
|
-
let loanTotalTime2Min = { loanTotalTime:
|
|
135
|
-
let loanTotalTime5Min = { loanTotalTime: 300, loanRenewAtLast:
|
|
134
|
+
let loanTotalTime2Min = { loanTotalTime: 10, loanRenewAtLast: 5, pageChangedInLast: 5 };
|
|
135
|
+
let loanTotalTime5Min = { loanTotalTime: 300, loanRenewAtLast: 290, pageChangedInLast: 15 };
|
|
136
136
|
let loanTotalTime1Hour = { loanTotalTime: 3600, loanRenewAtLast: 600, pageChangedInLast: 900 };
|
|
137
137
|
|
|
138
|
-
iaBookActions.loanRenewTimeConfig =
|
|
138
|
+
iaBookActions.loanRenewTimeConfig = loanTotalTime2Min;
|
|
139
139
|
|
|
140
140
|
let lendingStatus1 = iaBookActions.lendingStatus;
|
|
141
141
|
let secondsLeftOnLoan = iaBookActions.loanRenewTimeConfig.loanTotalTime;
|
package/package.json
CHANGED
|
@@ -32,7 +32,8 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
32
32
|
dropdownArrow: { type: String },
|
|
33
33
|
disabled: { type: Boolean },
|
|
34
34
|
returnUrl: { type: String },
|
|
35
|
-
|
|
35
|
+
autoRenew: { type: Boolean },
|
|
36
|
+
autoReturn: { type: Boolean },
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -52,7 +53,8 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
52
53
|
this.loaderIcon = 'https://archive.org/upload/images/tree/loading.gif';
|
|
53
54
|
this.disabled = false;
|
|
54
55
|
this.returnUrl = '';
|
|
55
|
-
this.
|
|
56
|
+
this.autoRenew = false;
|
|
57
|
+
this.autoReturn = false;
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
updated(changed) {
|
|
@@ -63,21 +65,33 @@ export class CollapsibleActionGroup extends ActionsHandler {
|
|
|
63
65
|
this.resetActions();
|
|
64
66
|
}
|
|
65
67
|
|
|
66
|
-
if (changed.has('
|
|
67
|
-
this.
|
|
68
|
+
if (changed.has('autoRenew') && this.autoRenew === true) {
|
|
69
|
+
this.dispatchLoanEvent('autoRenew');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (changed.has('autoReturn') && this.autoReturn === true) {
|
|
73
|
+
this.dispatchLoanEvent('autoReturn');
|
|
68
74
|
}
|
|
69
75
|
}
|
|
70
76
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
/**
|
|
78
|
+
* dispatch event when book is auto renewed / returned
|
|
79
|
+
* listen these events in action-handler.js
|
|
80
|
+
* @see ActionsHandler
|
|
81
|
+
*
|
|
82
|
+
* @param {string} event - autoRenew|autoReturn
|
|
83
|
+
* @memberof CollapsibleActionGroup
|
|
84
|
+
*/
|
|
85
|
+
dispatchLoanEvent(event) {
|
|
86
|
+
const category = analyticsCategories.browse;
|
|
87
|
+
const action =
|
|
88
|
+
event === 'autoRenew'
|
|
89
|
+
? analyticsActions.browseAutoRenew
|
|
90
|
+
: analyticsActions.browseAutoReturn;
|
|
77
91
|
|
|
78
92
|
// listen in action-handler.js to execute ajax call on petabox.
|
|
79
93
|
this.dispatchEvent(
|
|
80
|
-
new CustomEvent(
|
|
94
|
+
new CustomEvent(event, {
|
|
81
95
|
detail: {
|
|
82
96
|
event: { category, action },
|
|
83
97
|
},
|
|
@@ -31,43 +31,51 @@ export default class TimerCountdown extends LitElement {
|
|
|
31
31
|
*/
|
|
32
32
|
this.loanRenewAtLast = 0;
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* store time when timer is started
|
|
36
|
+
* @type {string}
|
|
37
|
+
*/
|
|
38
|
+
this.timeWhenTimerStart = '';
|
|
39
|
+
|
|
34
40
|
/**
|
|
35
41
|
* delay seconds in setInterval function
|
|
36
42
|
* @type {number}
|
|
37
43
|
*/
|
|
38
|
-
this.timerExecutionSeconds =
|
|
44
|
+
this.timerExecutionSeconds = 60;
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
disconnectedCallback() {
|
|
42
48
|
window?.IALendingIntervals?.clearTimerCountdown();
|
|
43
49
|
}
|
|
44
50
|
|
|
51
|
+
firstUpdated() {
|
|
52
|
+
this.timerCountdown();
|
|
53
|
+
}
|
|
54
|
+
|
|
45
55
|
updated(changed) {
|
|
46
56
|
if (changed.has('secondsLeftOnLoan') && this.secondsLeftOnLoan > 0) {
|
|
47
|
-
this.disconnectedCallback();
|
|
48
|
-
|
|
49
57
|
this.timerCountdown();
|
|
50
58
|
}
|
|
51
59
|
}
|
|
52
60
|
|
|
53
61
|
timerCountdown() {
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
this.disconnectedCallback();
|
|
63
|
+
|
|
64
|
+
let secondsLeft = this.secondsLeftOnLoan;
|
|
65
|
+
|
|
66
|
+
// store current time
|
|
67
|
+
this.timeWhenTimerStart = new Date();
|
|
56
68
|
|
|
57
69
|
/**
|
|
58
70
|
* set interval in window object
|
|
59
71
|
* @see ia-lending-intervals.js
|
|
60
72
|
*/
|
|
61
|
-
window.IALendingIntervals.timerCountdown = setInterval(() => {
|
|
62
|
-
|
|
63
|
-
|
|
73
|
+
window.IALendingIntervals.timerCountdown = setInterval(async () => {
|
|
74
|
+
secondsLeft -= this.timerExecutionSeconds;
|
|
75
|
+
secondsLeft = Math.round(secondsLeft); // round number
|
|
64
76
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
secondsLeft,
|
|
68
|
-
' ||| timeLeftInMin',
|
|
69
|
-
Math.ceil(secondsLeft / 60)
|
|
70
|
-
);
|
|
77
|
+
// re-sync timer is gone off
|
|
78
|
+
await this.reSyncTimerIfGoneOff(secondsLeft);
|
|
71
79
|
|
|
72
80
|
/**
|
|
73
81
|
* execute from last 10th minute to 0th minute
|
|
@@ -76,26 +84,74 @@ export default class TimerCountdown extends LitElement {
|
|
|
76
84
|
* @see IABookActions::bindLoanRenewEvents
|
|
77
85
|
*/
|
|
78
86
|
if (secondsLeft <= this.loanRenewAtLast) {
|
|
79
|
-
this.
|
|
80
|
-
new CustomEvent('IABookActions:loanRenew', {
|
|
81
|
-
detail: {
|
|
82
|
-
hasPageChanged: false,
|
|
83
|
-
secondsLeft,
|
|
84
|
-
},
|
|
85
|
-
bubbles: true,
|
|
86
|
-
composed: true,
|
|
87
|
-
})
|
|
88
|
-
);
|
|
87
|
+
this.dispatchLoanRenewEvent(secondsLeft);
|
|
89
88
|
}
|
|
90
89
|
|
|
91
|
-
// clear interval
|
|
92
|
-
if (secondsLeft <=
|
|
90
|
+
// clear interval in secondsLeft if less
|
|
91
|
+
if (secondsLeft <= this.timerExecutionSeconds) {
|
|
93
92
|
this.disconnectedCallback();
|
|
94
93
|
window?.Sentry?.captureMessage(sentryLogs.clearOneHourTimer);
|
|
95
94
|
}
|
|
96
95
|
}, this.timerExecutionSeconds * 1000);
|
|
97
96
|
}
|
|
98
97
|
|
|
98
|
+
/**
|
|
99
|
+
* dispatch loan renew attempt event
|
|
100
|
+
*
|
|
101
|
+
* @param {number} secondsLeft
|
|
102
|
+
* @memberof TimerCountdown
|
|
103
|
+
*/
|
|
104
|
+
dispatchLoanRenewEvent(secondsLeft) {
|
|
105
|
+
this.dispatchEvent(
|
|
106
|
+
new CustomEvent('IABookActions:loanRenew', {
|
|
107
|
+
detail: {
|
|
108
|
+
hasPageChanged: false,
|
|
109
|
+
secondsLeft,
|
|
110
|
+
},
|
|
111
|
+
bubbles: true,
|
|
112
|
+
composed: true,
|
|
113
|
+
})
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* helper function to determine if timer is not in sync properly
|
|
119
|
+
*
|
|
120
|
+
* @param {number} timerSecondsLeft - actual seconds left get from setInterval
|
|
121
|
+
*
|
|
122
|
+
* @memberof TimerCountdown
|
|
123
|
+
*/
|
|
124
|
+
async reSyncTimerIfGoneOff(timerSecondsLeft) {
|
|
125
|
+
// debug info
|
|
126
|
+
console.log(
|
|
127
|
+
new Date().toLocaleTimeString(),
|
|
128
|
+
'timeLeftInSec',
|
|
129
|
+
timerSecondsLeft,
|
|
130
|
+
' ||| timeLeftInMin',
|
|
131
|
+
Math.ceil(timerSecondsLeft / 60)
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
const currentTime = new Date();
|
|
135
|
+
|
|
136
|
+
// current time - loan time
|
|
137
|
+
const diffInSeconds =
|
|
138
|
+
currentTime.getTime() / 1000 - this.timeWhenTimerStart.getTime() / 1000;
|
|
139
|
+
|
|
140
|
+
const secondsShouldLeft = this.secondsLeftOnLoan - diffInSeconds;
|
|
141
|
+
|
|
142
|
+
// convert in minutes
|
|
143
|
+
const whatIsleft = Math.round(timerSecondsLeft);
|
|
144
|
+
const whatShouldLeft = Math.round(secondsShouldLeft);
|
|
145
|
+
|
|
146
|
+
if (whatIsleft !== whatShouldLeft) {
|
|
147
|
+
// debug info
|
|
148
|
+
console.log(
|
|
149
|
+
`timer is gone off, let's re-sync, whatIsleft -> ${whatIsleft}, whatShouldLeft -> ${whatShouldLeft}`
|
|
150
|
+
);
|
|
151
|
+
this.secondsLeftOnLoan = secondsShouldLeft; // the seconds should left in timer again
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
99
155
|
/**
|
|
100
156
|
* get remaining time with timeunit
|
|
101
157
|
*
|
|
@@ -13,7 +13,8 @@ export const analyticsCategories = {
|
|
|
13
13
|
export const analyticsActions = {
|
|
14
14
|
browse: 'Borrow-1Hour',
|
|
15
15
|
browseAgain: 'Borrow-Again',
|
|
16
|
-
|
|
16
|
+
browseAutoRenew: 'AutoRenewBook',
|
|
17
|
+
browseAutoReturn: 'AutoReturnBook',
|
|
17
18
|
borrow: 'Borrow-14Days',
|
|
18
19
|
waitlistJoin: 'JoinWaitlist',
|
|
19
20
|
waitlistLeave: 'LeaveWaitlist',
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
2
|
|
|
3
3
|
import { URLHelper } from '../../config/url-helper.js';
|
|
4
|
-
import { sentryLogs } from '../../config/sentry-events.js';
|
|
5
4
|
|
|
6
5
|
import ActionsHandlerService from './actions-handler-service.js';
|
|
6
|
+
import LoanAnanlytics from '../loan-analytics.js';
|
|
7
7
|
import * as Cookies from '../doc-cookies.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* These are callback functions calling from actions-config.js file.
|
|
11
11
|
*
|
|
12
|
-
* ActionsHandlerService is a function being used to execute
|
|
13
|
-
*
|
|
14
|
-
* 1. identifier: book name.
|
|
12
|
+
* ActionsHandlerService is a function being used to execute APIs based of the request made by user.
|
|
13
|
+
*
|
|
15
14
|
*/
|
|
16
15
|
|
|
17
16
|
export default class ActionsHandler extends LitElement {
|
|
@@ -24,86 +23,148 @@ export default class ActionsHandler extends LitElement {
|
|
|
24
23
|
*/
|
|
25
24
|
this.waitUntillBorrowComplete = 6; // in seconds
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
/**
|
|
27
|
+
* bind events for lending bar
|
|
28
|
+
* @type {object}
|
|
29
|
+
*/
|
|
30
|
+
this.loanAnanlytics = new LoanAnanlytics();
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
);
|
|
32
|
+
/**
|
|
33
|
+
* bind events for lending bar
|
|
34
|
+
* @type {Function}
|
|
35
|
+
*/
|
|
36
|
+
this.bindEvents();
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
bindEvents() {
|
|
39
40
|
this.addEventListener('browseBook', ({ detail }) => {
|
|
40
41
|
this.handleBrowseIt();
|
|
41
|
-
this.
|
|
42
|
+
this.loanAnanlytics?.storeLoanStatsCount(this.identifier, 'browse');
|
|
42
43
|
const { category, action } = detail.event;
|
|
43
|
-
this.sendEvent(
|
|
44
|
+
this.loanAnanlytics?.sendEvent(
|
|
45
|
+
category,
|
|
46
|
+
action,
|
|
47
|
+
`identifier=${this.identifier}`
|
|
48
|
+
);
|
|
44
49
|
});
|
|
45
50
|
|
|
46
51
|
this.addEventListener('browseBookAgain', ({ detail }) => {
|
|
47
52
|
this.handleBrowseIt();
|
|
48
|
-
this.
|
|
53
|
+
this.loanAnanlytics?.storeLoanStatsCount(this.identifier, 'browseagain');
|
|
49
54
|
const { category, action } = detail.event;
|
|
50
|
-
this.sendEvent(
|
|
55
|
+
this.loanAnanlytics?.sendEvent(
|
|
56
|
+
category,
|
|
57
|
+
action,
|
|
58
|
+
`identifier=${this.identifier}`
|
|
59
|
+
);
|
|
51
60
|
});
|
|
52
61
|
|
|
53
|
-
this.addEventListener('
|
|
54
|
-
this.
|
|
62
|
+
this.addEventListener('autoRenew', ({ detail }) => {
|
|
63
|
+
this.handleLoanRenewNow();
|
|
64
|
+
this.loanAnanlytics?.storeLoanStatsCount(this.identifier, 'autorenew');
|
|
55
65
|
const { category, action } = detail.event;
|
|
56
|
-
this.sendEvent(
|
|
66
|
+
this.loanAnanlytics?.sendEvent(
|
|
67
|
+
category,
|
|
68
|
+
action,
|
|
69
|
+
`identifier=${this.identifier}`
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
this.addEventListener('autoReturn', ({ detail }) => {
|
|
74
|
+
this.loanAnanlytics?.storeLoanStatsCount(this.identifier, 'autoreturn');
|
|
75
|
+
const { category, action } = detail.event;
|
|
76
|
+
this.loanAnanlytics?.sendEvent(
|
|
77
|
+
category,
|
|
78
|
+
action,
|
|
79
|
+
`identifier=${this.identifier}`
|
|
80
|
+
);
|
|
57
81
|
});
|
|
58
82
|
|
|
59
83
|
this.addEventListener('returnNow', ({ detail }) => {
|
|
84
|
+
this.loanAnanlytics?.storeLoanStatsCount(this.identifier, 'return');
|
|
60
85
|
this.handleReturnIt();
|
|
61
86
|
const { category, action } = detail.event;
|
|
62
|
-
this.sendEvent(
|
|
87
|
+
this.loanAnanlytics?.sendEvent(
|
|
88
|
+
category,
|
|
89
|
+
action,
|
|
90
|
+
`identifier=${this.identifier}`
|
|
91
|
+
);
|
|
63
92
|
});
|
|
64
93
|
|
|
65
94
|
this.addEventListener('borrowBook', ({ detail }) => {
|
|
66
95
|
this.handleBorrowIt();
|
|
67
96
|
const { category, action } = detail.event;
|
|
68
|
-
this.sendEvent(
|
|
97
|
+
this.loanAnanlytics?.sendEvent(
|
|
98
|
+
category,
|
|
99
|
+
action,
|
|
100
|
+
`identifier=${this.identifier}`
|
|
101
|
+
);
|
|
69
102
|
});
|
|
70
103
|
|
|
71
104
|
this.addEventListener('loginAndBorrow', ({ detail }) => {
|
|
72
105
|
this.handleLoginOk();
|
|
73
106
|
const { category, action } = detail.event;
|
|
74
|
-
this.sendEvent(
|
|
107
|
+
this.loanAnanlytics?.sendEvent(
|
|
108
|
+
category,
|
|
109
|
+
action,
|
|
110
|
+
`identifier=${this.identifier}`
|
|
111
|
+
);
|
|
75
112
|
});
|
|
76
113
|
|
|
77
114
|
this.addEventListener('leaveWaitlist', ({ detail }) => {
|
|
78
115
|
this.handleRemoveFromWaitingList();
|
|
79
116
|
const { category, action } = detail.event;
|
|
80
|
-
this.sendEvent(
|
|
117
|
+
this.loanAnanlytics?.sendEvent(
|
|
118
|
+
category,
|
|
119
|
+
action,
|
|
120
|
+
`identifier=${this.identifier}`
|
|
121
|
+
);
|
|
81
122
|
});
|
|
82
123
|
|
|
83
124
|
this.addEventListener('joinWaitlist', ({ detail }) => {
|
|
84
125
|
this.handleReserveIt();
|
|
85
126
|
const { category, action } = detail.event;
|
|
86
|
-
this.sendEvent(
|
|
127
|
+
this.loanAnanlytics?.sendEvent(
|
|
128
|
+
category,
|
|
129
|
+
action,
|
|
130
|
+
`identifier=${this.identifier}`
|
|
131
|
+
);
|
|
87
132
|
});
|
|
88
133
|
|
|
89
134
|
this.addEventListener('purchaseBook', ({ detail }) => {
|
|
90
135
|
const { category, action } = detail.event;
|
|
91
|
-
this.sendEvent(
|
|
136
|
+
this.loanAnanlytics?.sendEvent(
|
|
137
|
+
category,
|
|
138
|
+
action,
|
|
139
|
+
`identifier=${this.identifier}`
|
|
140
|
+
);
|
|
92
141
|
});
|
|
93
142
|
|
|
94
143
|
this.addEventListener('adminAccess', ({ detail }) => {
|
|
95
144
|
const { category, action } = detail.event;
|
|
96
|
-
this.sendEvent(
|
|
145
|
+
this.loanAnanlytics?.sendEvent(
|
|
146
|
+
category,
|
|
147
|
+
action,
|
|
148
|
+
`identifier=${this.identifier}`
|
|
149
|
+
);
|
|
97
150
|
});
|
|
98
151
|
|
|
99
152
|
this.addEventListener('exitAdminAccess', ({ detail }) => {
|
|
100
153
|
const { category, action } = detail.event;
|
|
101
|
-
this.sendEvent(
|
|
154
|
+
this.loanAnanlytics?.sendEvent(
|
|
155
|
+
category,
|
|
156
|
+
action,
|
|
157
|
+
`identifier=${this.identifier}`
|
|
158
|
+
);
|
|
102
159
|
});
|
|
103
160
|
|
|
104
161
|
this.addEventListener('bookTitleBar', ({ detail }) => {
|
|
105
162
|
const { category, action } = detail.event;
|
|
106
|
-
this.sendEvent(
|
|
163
|
+
this.loanAnanlytics?.sendEvent(
|
|
164
|
+
category,
|
|
165
|
+
action,
|
|
166
|
+
`identifier=${this.identifier}`
|
|
167
|
+
);
|
|
107
168
|
});
|
|
108
169
|
}
|
|
109
170
|
|
|
@@ -124,7 +185,7 @@ export default class ActionsHandler extends LitElement {
|
|
|
124
185
|
});
|
|
125
186
|
}
|
|
126
187
|
|
|
127
|
-
|
|
188
|
+
handleLoanRenewNow() {
|
|
128
189
|
const action = 'renew_loan';
|
|
129
190
|
|
|
130
191
|
ActionsHandlerService({
|
|
@@ -220,7 +281,7 @@ export default class ActionsHandler extends LitElement {
|
|
|
220
281
|
*/
|
|
221
282
|
dispatchActionError(action, data = {}) {
|
|
222
283
|
// send LendingServiceError to GA
|
|
223
|
-
this.sendEvent('LendingServiceError', action);
|
|
284
|
+
this.loanAnanlytics?.sendEvent('LendingServiceError', action);
|
|
224
285
|
|
|
225
286
|
this.dispatchEvent(
|
|
226
287
|
new CustomEvent('lendingActionError', {
|
|
@@ -271,31 +332,6 @@ export default class ActionsHandler extends LitElement {
|
|
|
271
332
|
}, this.waitUntillBorrowComplete * 1000);
|
|
272
333
|
}
|
|
273
334
|
|
|
274
|
-
// save consecutive loan count for borrow
|
|
275
|
-
async setConsecutiveLoanCounts(action = '') {
|
|
276
|
-
try {
|
|
277
|
-
let newCount = 1;
|
|
278
|
-
const storageKey = `loan-count-${this.identifier}`;
|
|
279
|
-
const existingCount = Cookies.getItem(storageKey);
|
|
280
|
-
|
|
281
|
-
// increase browse-count by 1 when you consecutive reading a book.
|
|
282
|
-
if (action === 'browseAgain' && existingCount !== undefined) {
|
|
283
|
-
newCount = existingCount ? Number(existingCount) + 1 : 1;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
const date = new Date();
|
|
287
|
-
date.setHours(date.getHours() + 2); // 2 hours
|
|
288
|
-
|
|
289
|
-
// set new value
|
|
290
|
-
Cookies.setItem(storageKey, newCount, date, '/');
|
|
291
|
-
} catch (error) {
|
|
292
|
-
window?.Sentry?.captureException(
|
|
293
|
-
`${sentryLogs.setConsecutiveLoanCounts} - Error: ${error}`
|
|
294
|
-
);
|
|
295
|
-
this.sendEvent('Cookies-Error-Actions', error);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
335
|
/**
|
|
300
336
|
* set browse time in indexedDB
|
|
301
337
|
*/
|
|
@@ -62,7 +62,7 @@ export function setItem(sKey, sValue, vEnd, sPath, sDomain, bSecure) {
|
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* BROKEN Remove specific key's value from cookie
|
|
65
|
-
*
|
|
65
|
+
*
|
|
66
66
|
* @param {string} sKey cookie name
|
|
67
67
|
* @param {string} [sPath] path of current item
|
|
68
68
|
* @param {string} [sDomain]
|
|
@@ -81,3 +81,25 @@ export function removeItem(sKey, sPath, sDomain) {
|
|
|
81
81
|
|
|
82
82
|
return true;
|
|
83
83
|
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* determine if a specific cookie is exist
|
|
87
|
+
*
|
|
88
|
+
* @param {string} sKey cookie name
|
|
89
|
+
*
|
|
90
|
+
* @returns {boolean}
|
|
91
|
+
*/
|
|
92
|
+
export function hasItem(sKey) {
|
|
93
|
+
const reCNameAllowed = /^(?:expires|max\-age|path|domain|secure|samesite|httponly)$/i;
|
|
94
|
+
|
|
95
|
+
// eslint-disable-next-line
|
|
96
|
+
if (!sKey || reCNameAllowed.test(sKey)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return new RegExp(
|
|
101
|
+
'(?:^|;\\s*)' +
|
|
102
|
+
encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, '\\$&') +
|
|
103
|
+
'\\s*\\='
|
|
104
|
+
).test(document.cookie);
|
|
105
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/* eslint-disable class-methods-use-this */
|
|
2
|
+
|
|
3
|
+
import { analyticsCategories } from '../config/analytics-event-and-category.js';
|
|
4
|
+
import * as Cookies from './doc-cookies.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This class is used to send different GA events for loan system.
|
|
8
|
+
*/
|
|
9
|
+
export default class LoanAnanlytics {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.identifier = undefined;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* contains the counts we send to GA
|
|
15
|
+
* @type {object}
|
|
16
|
+
* - @param {number} - browse count
|
|
17
|
+
* - @param {number} - renew count
|
|
18
|
+
* - @param {number} - expire count
|
|
19
|
+
*/
|
|
20
|
+
this.gaStats = {};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* store loan stats count in cookies to remember the count we need to sent GA
|
|
25
|
+
*
|
|
26
|
+
* @param {string} identifier - book id
|
|
27
|
+
* @param {string} action - user action on book
|
|
28
|
+
* @return {void}
|
|
29
|
+
* @memberof ActionsHandler
|
|
30
|
+
*/
|
|
31
|
+
async storeLoanStatsCount(idetifier, action = '') {
|
|
32
|
+
this.identifier = idetifier;
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
await this.getLoanStatsCount(action);
|
|
36
|
+
|
|
37
|
+
const date = new Date();
|
|
38
|
+
date.setHours(date.getHours() + 2); // 2 hours
|
|
39
|
+
|
|
40
|
+
// set new value
|
|
41
|
+
Cookies.setItem(
|
|
42
|
+
this.getLoanCountStorageKey,
|
|
43
|
+
JSON.stringify(this.lendingEventCounts),
|
|
44
|
+
date,
|
|
45
|
+
'/'
|
|
46
|
+
);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.log(error);
|
|
49
|
+
this.sendEvent(
|
|
50
|
+
'Cookies-Error-Actions',
|
|
51
|
+
error,
|
|
52
|
+
`identifier=${this.identifier}`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* get loan stats count from cookies for GA
|
|
59
|
+
*
|
|
60
|
+
* @param {string} action 'browse'|'autorenew'|etc...
|
|
61
|
+
* @memberof ActionsHandler
|
|
62
|
+
*/
|
|
63
|
+
async getLoanStatsCount(action) {
|
|
64
|
+
this.lendingEventCounts = JSON.parse(
|
|
65
|
+
Cookies.getItem(this.getLoanCountStorageKey)
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
this.gaStats = this.lendingEventCounts ?? {
|
|
69
|
+
browse: 0,
|
|
70
|
+
renew: 0,
|
|
71
|
+
expire: 0,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
let { browse, renew, expire } = this.lendingEventCounts ?? 0;
|
|
75
|
+
|
|
76
|
+
switch (action) {
|
|
77
|
+
case 'browse' || 'browseagain':
|
|
78
|
+
browse = browse ? Number(browse) + 1 : 1;
|
|
79
|
+
this.gaStats.browse = browse;
|
|
80
|
+
|
|
81
|
+
// reset renew and expire count when browse
|
|
82
|
+
renew = 0;
|
|
83
|
+
expire = 0;
|
|
84
|
+
break;
|
|
85
|
+
|
|
86
|
+
case 'autorenew':
|
|
87
|
+
renew = renew ? Number(renew) + 1 : 1;
|
|
88
|
+
this.gaStats.renew = renew;
|
|
89
|
+
break;
|
|
90
|
+
|
|
91
|
+
case 'return' || 'autoreturn':
|
|
92
|
+
expire = expire ? Number(expire) + 1 : 1;
|
|
93
|
+
this.gaStats.expire = expire;
|
|
94
|
+
|
|
95
|
+
// reset renew and expire count when browse
|
|
96
|
+
renew = 0;
|
|
97
|
+
expire = 0;
|
|
98
|
+
break;
|
|
99
|
+
default:
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// store these counts in cookies
|
|
104
|
+
this.lendingEventCounts = { browse, renew, expire };
|
|
105
|
+
|
|
106
|
+
// obtain GA category, event
|
|
107
|
+
// const { category, event } = await this.getGACategoryAction(action);
|
|
108
|
+
const category = analyticsCategories.browse;
|
|
109
|
+
const event = `browse${this.paddedNumber(
|
|
110
|
+
this.gaStats?.browse
|
|
111
|
+
)}-autorenew${this.paddedNumber(this.gaStats?.renew)}:${action}`;
|
|
112
|
+
|
|
113
|
+
// send google analytics events
|
|
114
|
+
this.sendEvent(category, event, `identifier=${this.identifier}`, {
|
|
115
|
+
browse: this.gaStats?.browse,
|
|
116
|
+
renew: this.gaStats?.renew,
|
|
117
|
+
expire: this.gaStats?.expire,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
*
|
|
123
|
+
*
|
|
124
|
+
* @param {string} action - like 'browse|autorenew|etc...'
|
|
125
|
+
* @return {object} - contains GA category and event
|
|
126
|
+
* - @param {string}
|
|
127
|
+
* - @param {string}
|
|
128
|
+
*
|
|
129
|
+
* @memberof LoanAnanlytics
|
|
130
|
+
*/
|
|
131
|
+
getGACategoryAction(action) {
|
|
132
|
+
const GACategory = analyticsCategories.browse;
|
|
133
|
+
const GAAction = `browse${this.paddedNumber(
|
|
134
|
+
this.gaStats?.browse
|
|
135
|
+
)}-autorenew${this.paddedNumber(this.gaStats?.renew)}:${action}`;
|
|
136
|
+
|
|
137
|
+
return { GACategory, GAAction };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* get zero padded number
|
|
142
|
+
*
|
|
143
|
+
* @param {number} number
|
|
144
|
+
* @return {string} browse001|autorenew001
|
|
145
|
+
* @memberof LoanAnanlytics
|
|
146
|
+
*/
|
|
147
|
+
paddedNumber(number) {
|
|
148
|
+
return number.toString().padStart(3, '0');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* get storage key for loan stats count
|
|
153
|
+
*
|
|
154
|
+
* @readonly
|
|
155
|
+
* @memberof LoanAnanlytics
|
|
156
|
+
*/
|
|
157
|
+
get getLoanCountStorageKey() {
|
|
158
|
+
return `br-browse-${this.identifier}`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* reponsible to sent events to GA
|
|
163
|
+
*
|
|
164
|
+
* @param {*} eventCategory
|
|
165
|
+
* @param {*} eventAction
|
|
166
|
+
* @param {*} label
|
|
167
|
+
* @param {*} extraParams
|
|
168
|
+
* @memberof LoanAnanlytics
|
|
169
|
+
*/
|
|
170
|
+
sendEvent(eventCategory, eventAction, label, extraParams) {
|
|
171
|
+
console.debug(
|
|
172
|
+
'eventCategory:- ',
|
|
173
|
+
eventCategory,
|
|
174
|
+
'\neventAction:- ',
|
|
175
|
+
eventAction,
|
|
176
|
+
'\nlabel:- ',
|
|
177
|
+
label,
|
|
178
|
+
'\nextraParams:- ',
|
|
179
|
+
extraParams
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
window?.archive_analytics?.send_event_no_sampling(
|
|
183
|
+
eventCategory,
|
|
184
|
+
eventAction,
|
|
185
|
+
label || `identifier=${this.identifier}`,
|
|
186
|
+
extraParams
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import ActionsHandlerService from './actions-handler/actions-handler-service.js';
|
|
2
|
+
import LoanAnanlytics from './loan-analytics.js';
|
|
2
3
|
import { sentryLogs } from '../config/sentry-events.js';
|
|
3
4
|
|
|
4
5
|
import * as Cookies from './doc-cookies.js';
|
|
@@ -17,6 +18,13 @@ export class LoanTokenPoller {
|
|
|
17
18
|
this.pollerDelay = pollerDelay; // value in seconds
|
|
18
19
|
|
|
19
20
|
this.loanTokenInterval = undefined;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* loan analytics instance
|
|
24
|
+
* @see loan-analytics.js
|
|
25
|
+
*/
|
|
26
|
+
this.loanAnalytics = new LoanAnanlytics();
|
|
27
|
+
|
|
20
28
|
this.bookAccessed();
|
|
21
29
|
}
|
|
22
30
|
|
|
@@ -39,7 +47,6 @@ export class LoanTokenPoller {
|
|
|
39
47
|
window?.Sentry?.captureException(
|
|
40
48
|
`${sentryLogs.enableBookAcces} - CookieError: ${error}`
|
|
41
49
|
);
|
|
42
|
-
this.sendEvent('Cookies-Error-Token', error);
|
|
43
50
|
}
|
|
44
51
|
}
|
|
45
52
|
|
|
@@ -65,7 +72,11 @@ export class LoanTokenPoller {
|
|
|
65
72
|
this.borrowType === 'browsed' ? 'BrowseCounts-' : 'Counts-'
|
|
66
73
|
}${consecutiveLoanCounts}`;
|
|
67
74
|
|
|
68
|
-
this.sendEvent(
|
|
75
|
+
this.loanAnalytics?.sendEvent(
|
|
76
|
+
category,
|
|
77
|
+
action,
|
|
78
|
+
`identifier=${this.identifier}`
|
|
79
|
+
);
|
|
69
80
|
} else {
|
|
70
81
|
window?.Sentry?.captureMessage(
|
|
71
82
|
`${sentryLogs.bookAccessed} - not borrowed`
|
|
@@ -76,14 +87,6 @@ export class LoanTokenPoller {
|
|
|
76
87
|
}
|
|
77
88
|
}
|
|
78
89
|
|
|
79
|
-
sendEvent(eventCategory, eventAction) {
|
|
80
|
-
window?.archive_analytics?.send_event(
|
|
81
|
-
eventCategory,
|
|
82
|
-
eventAction,
|
|
83
|
-
`identifier=${this.identifier}`
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
90
|
async handleLoanTokenPoller(isInitial = false) {
|
|
88
91
|
const action = 'create_token';
|
|
89
92
|
ActionsHandlerService({
|
|
@@ -98,7 +101,11 @@ export class LoanTokenPoller {
|
|
|
98
101
|
);
|
|
99
102
|
|
|
100
103
|
// send LendingServiceError to GA
|
|
101
|
-
this.sendEvent(
|
|
104
|
+
this.loanAnalytics?.sendEvent(
|
|
105
|
+
'LendingServiceLoanError',
|
|
106
|
+
action,
|
|
107
|
+
`identifier=${this.identifier}`
|
|
108
|
+
);
|
|
102
109
|
},
|
|
103
110
|
success: () => {
|
|
104
111
|
if (isInitial) this.successCallback();
|
package/src/ia-book-actions.js
CHANGED
|
@@ -11,7 +11,6 @@ import './components/book-title-bar.js';
|
|
|
11
11
|
import './components/text-group.js';
|
|
12
12
|
import './components/info-icon.js';
|
|
13
13
|
import './components/timer-countdown.js';
|
|
14
|
-
import './core/config/ia-lending-intervals.js';
|
|
15
14
|
|
|
16
15
|
import { GetLendingActions } from './core/services/get-lending-actions.js';
|
|
17
16
|
import { mobileContainerWidth } from './core/config/constants.js';
|
|
@@ -19,6 +18,9 @@ import { sentryLogs } from './core/config/sentry-events.js';
|
|
|
19
18
|
import { LoanTokenPoller } from './core/services/loan-token-poller.js';
|
|
20
19
|
import { LoanRenewHelper } from './core/services/loan-renew-helper.js';
|
|
21
20
|
|
|
21
|
+
import './core/config/ia-lending-intervals.js';
|
|
22
|
+
import * as Cookies from './core/services/doc-cookies.js';
|
|
23
|
+
|
|
22
24
|
export const events = {
|
|
23
25
|
browseExpired: 'IABookReader:BrowsingHasExpired',
|
|
24
26
|
};
|
|
@@ -236,16 +238,10 @@ export default class IABookActions extends LitElement {
|
|
|
236
238
|
/**
|
|
237
239
|
* tokenPoller determines if user has loan token for this book
|
|
238
240
|
* - if book is going to renew, need to wait until renew is completed
|
|
239
|
-
* - otherwise execute immediately
|
|
240
241
|
*/
|
|
241
|
-
setTimeout(
|
|
242
|
-
()
|
|
243
|
-
|
|
244
|
-
},
|
|
245
|
-
|
|
246
|
-
// if book is renew while reading, let's wait to execute create-token api
|
|
247
|
-
this.loanRenewResult.renewNow ? this.tokenDelay * 1000 : 100
|
|
248
|
-
);
|
|
242
|
+
setTimeout(() => {
|
|
243
|
+
if (!hasExpired) this.startLoanTokenPoller();
|
|
244
|
+
}, 100);
|
|
249
245
|
}
|
|
250
246
|
|
|
251
247
|
/**
|
|
@@ -260,12 +256,12 @@ export default class IABookActions extends LitElement {
|
|
|
260
256
|
* dispatched this event from bookreader page changed
|
|
261
257
|
*/
|
|
262
258
|
window.addEventListener('BookReader:userAction', () => {
|
|
259
|
+
this.suppressToast = true;
|
|
260
|
+
this.closeToastManager();
|
|
261
|
+
|
|
263
262
|
if (this.borrowType === 'browsed') {
|
|
264
|
-
this.suppressToast = false;
|
|
265
263
|
this.autoLoanRenewChecker(true);
|
|
266
264
|
}
|
|
267
|
-
|
|
268
|
-
return nothing;
|
|
269
265
|
});
|
|
270
266
|
|
|
271
267
|
/**
|
|
@@ -320,6 +316,16 @@ export default class IABookActions extends LitElement {
|
|
|
320
316
|
this.loanRenewResult = this.loanRenewHelper.result;
|
|
321
317
|
}
|
|
322
318
|
|
|
319
|
+
/**
|
|
320
|
+
* close/hide toast message
|
|
321
|
+
*/
|
|
322
|
+
async closeToastManager() {
|
|
323
|
+
const toastTemplate = this.shadowRoot.querySelector('toast-template');
|
|
324
|
+
if (toastTemplate) {
|
|
325
|
+
toastTemplate?.remove();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
323
329
|
/**
|
|
324
330
|
* Show toast messages on some specific loan renew features. e.g.
|
|
325
331
|
* - show message when book is auto renewed
|
|
@@ -329,14 +335,11 @@ export default class IABookActions extends LitElement {
|
|
|
329
335
|
async showToastMessage() {
|
|
330
336
|
if (this.suppressToast) return;
|
|
331
337
|
|
|
332
|
-
|
|
333
|
-
if (!iaBookActions) return;
|
|
334
|
-
|
|
335
|
-
let toastTemplate = iaBookActions.querySelector('toast-template');
|
|
338
|
+
let toastTemplate = this.shadowRoot.querySelector('toast-template');
|
|
336
339
|
if (!toastTemplate) {
|
|
337
340
|
toastTemplate = document.createElement('toast-template');
|
|
338
341
|
}
|
|
339
|
-
await
|
|
342
|
+
await this.shadowRoot.appendChild(toastTemplate);
|
|
340
343
|
|
|
341
344
|
// if secondsLeft < 60, consider it 1 minute
|
|
342
345
|
let { secondsLeft } = this.loanRenewResult;
|
|
@@ -402,6 +405,9 @@ export default class IABookActions extends LitElement {
|
|
|
402
405
|
await this.localCache.delete(`${this.identifier}-loanTime`);
|
|
403
406
|
await this.localCache.delete(`${this.identifier}-pageChangedTime`);
|
|
404
407
|
|
|
408
|
+
// remove loan-renew-count-<identifier> cookie
|
|
409
|
+
Cookies.removeItem(`loan-renew-count-${this.identifier}`);
|
|
410
|
+
|
|
405
411
|
// show message after browsed book is expired.
|
|
406
412
|
this.loanRenewResult.renewNow = false;
|
|
407
413
|
this.loanRenewResult.texts =
|
|
@@ -484,7 +490,8 @@ export default class IABookActions extends LitElement {
|
|
|
484
490
|
.loanTotalTime=${this.loanRenewTimeConfig.loanTotalTime}
|
|
485
491
|
?hasAdminAccess=${this.hasAdminAccess}
|
|
486
492
|
?disabled=${this.disableActionGroup}
|
|
487
|
-
?
|
|
493
|
+
?autoRenew=${this.loanRenewResult.renewNow}
|
|
494
|
+
?autoReturn=${this.lendingStatus.browsingExpired}
|
|
488
495
|
@loanAutoRenewed=${this.handleLoanAutoRenewed}
|
|
489
496
|
@lendingActionError=${this.handleLendingActionError}
|
|
490
497
|
@toggleActionGroup=${this.handleToggleActionGroup}
|
|
@@ -573,8 +580,7 @@ export default class IABookActions extends LitElement {
|
|
|
573
580
|
* @param {string} event.detail.data.error - error message
|
|
574
581
|
*/
|
|
575
582
|
handleLendingActionError(event) {
|
|
576
|
-
|
|
577
|
-
this.handleToggleActionGroup();
|
|
583
|
+
this.disableActionGroup = false;
|
|
578
584
|
|
|
579
585
|
// clear all intervals for lending system when error occured
|
|
580
586
|
window?.IALendingIntervals?.clearAll();
|
|
@@ -582,7 +588,9 @@ export default class IABookActions extends LitElement {
|
|
|
582
588
|
const action = event?.detail?.action;
|
|
583
589
|
const errorMsg = event?.detail?.data?.error;
|
|
584
590
|
|
|
585
|
-
|
|
591
|
+
// template not show create_token errors
|
|
592
|
+
if (errorMsg && action !== 'create_token')
|
|
593
|
+
this.showErrorModal(errorMsg, action);
|
|
586
594
|
|
|
587
595
|
// if error related to loan token
|
|
588
596
|
// - clear tokenPoller interval
|
|
@@ -616,8 +624,6 @@ export default class IABookActions extends LitElement {
|
|
|
616
624
|
|
|
617
625
|
/* show error message if something went wrong */
|
|
618
626
|
async showErrorModal(errorMsg, action) {
|
|
619
|
-
this.disableActionGroup = false;
|
|
620
|
-
|
|
621
627
|
// check if this.modal passed as prop
|
|
622
628
|
if (!this.modal) {
|
|
623
629
|
this.modal = document.querySelector('modal-manager');
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en-GB">
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="utf-8">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
7
|
-
<style>
|
|
8
|
-
html {
|
|
9
|
-
font-size: 10px;
|
|
10
|
-
/* This is to match petabox's base font size */
|
|
11
|
-
}
|
|
12
|
-
body {
|
|
13
|
-
margin: 0;
|
|
14
|
-
text-align: center;
|
|
15
|
-
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
16
|
-
}
|
|
17
|
-
#demo {
|
|
18
|
-
height: 50px;
|
|
19
|
-
}
|
|
20
|
-
ia-book-actions {
|
|
21
|
-
--white: #fff;
|
|
22
|
-
--black: #000;
|
|
23
|
-
--primaryBGColor: var(--black);
|
|
24
|
-
--secondaryBGColor: #222;
|
|
25
|
-
--tertiaryBGColor: #333;
|
|
26
|
-
--primaryTextColor: var(--white);
|
|
27
|
-
--primaryCTAFill: #194880;
|
|
28
|
-
--primaryCTABorder: #c5d1df;
|
|
29
|
-
--secondaryCTAFill: #333;
|
|
30
|
-
--secondaryCTABorder: #999;
|
|
31
|
-
--secondaryCTAFillRGB: 51, 51, 51;
|
|
32
|
-
--primaryErrorCTAFill: #e51c26;
|
|
33
|
-
--primaryErrorCTABorder: #f8c6c8;
|
|
34
|
-
--primaryCTAFillRGB: 25, 72, 128;
|
|
35
|
-
--primaryErrorCTAFillRGB: 229, 28, 38;
|
|
36
|
-
--primaryDisableCTAFill: #767676;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
fieldset {
|
|
40
|
-
width: fit-content;
|
|
41
|
-
margin-top: 50px;
|
|
42
|
-
}
|
|
43
|
-
fieldset legend {
|
|
44
|
-
text-align: left;
|
|
45
|
-
font-size: 12px;
|
|
46
|
-
}
|
|
47
|
-
td {
|
|
48
|
-
color: white;
|
|
49
|
-
font-size: 14px;
|
|
50
|
-
border-radius: 5%;
|
|
51
|
-
display: table-cell;
|
|
52
|
-
text-align: initial;
|
|
53
|
-
margin: 5px 0;
|
|
54
|
-
width: max-content;
|
|
55
|
-
display: block;
|
|
56
|
-
}
|
|
57
|
-
label {
|
|
58
|
-
padding: 10px;
|
|
59
|
-
display: block;
|
|
60
|
-
cursor: pointer;
|
|
61
|
-
margin: 2px;
|
|
62
|
-
background: #4e545a;
|
|
63
|
-
border-radius: 10px;
|
|
64
|
-
}
|
|
65
|
-
input[type="radio"], input[type="checkbox"] {
|
|
66
|
-
margin-top: 0;
|
|
67
|
-
vertical-align: middle;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.initial td {
|
|
71
|
-
float: left;
|
|
72
|
-
margin: 2px;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
body.modal-manager-open {
|
|
76
|
-
overflow: hidden;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
modal-manager[mode='closed'] {
|
|
80
|
-
display: none;
|
|
81
|
-
}
|
|
82
|
-
</style>
|
|
83
|
-
</head>
|
|
84
|
-
|
|
85
|
-
<body>
|
|
86
|
-
<ia-bookreader class="focus-on-child-only" signedin="" fullscreen="">
|
|
87
|
-
<div slot="header">
|
|
88
|
-
<ia-book-actions></ia-book-actions>
|
|
89
|
-
</div>
|
|
90
|
-
<div slot="main">
|
|
91
|
-
<div id="BookReader"></div>
|
|
92
|
-
</div>
|
|
93
|
-
</ia-bookreader>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
<script type="module">
|
|
97
|
-
/* eslint-disable */
|
|
98
|
-
import '@internetarchive/bookreader';
|
|
99
|
-
import '@internetarchive/bookreader/BookReader/jquery-1.10.1.js';
|
|
100
|
-
import '@internetarchive/bookreader/BookReader/BookReader.js';
|
|
101
|
-
import '../src/ia-book-actions.js';
|
|
102
|
-
import {
|
|
103
|
-
defaultLendingStatus,
|
|
104
|
-
canBrowseAndBorrow,
|
|
105
|
-
} from '../src/assets/data/lending-get-status-service.js';
|
|
106
|
-
import { ModalConfig } from '@internetarchive/modal-manager';
|
|
107
|
-
|
|
108
|
-
const userid = '@neeraj-archive';
|
|
109
|
-
const identifier = 'naturalhistoryof00unse_4111';
|
|
110
|
-
let bwbPurchaseUrl = 'https://www.betterworldbooks.com/product/detail/cambridge-ancient-hist-v04-0521044863';
|
|
111
|
-
|
|
112
|
-
let iaBookActions = document.querySelector('ia-book-actions');
|
|
113
|
-
|
|
114
|
-
// for debugging
|
|
115
|
-
window.iaBookActions = iaBookActions;
|
|
116
|
-
|
|
117
|
-
const modalConfig = new ModalConfig();
|
|
118
|
-
modalConfig.headerColor = '#d9534f';
|
|
119
|
-
|
|
120
|
-
let lendingBarPostInit = function lendingBarPostInit() {
|
|
121
|
-
setTimeout(function() {
|
|
122
|
-
console.log('executed', 'br.init()');
|
|
123
|
-
}, 100);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// set defaultLendingStatus for unavailable (without borrowables) book
|
|
127
|
-
iaBookActions.userid = userid;
|
|
128
|
-
iaBookActions.identifier = identifier;
|
|
129
|
-
iaBookActions.bookTitle = 'Contemporary Black biography. Volume 39 : profiles from the interContemporary Black biography. Volume 39';
|
|
130
|
-
iaBookActions.lendingStatus = canBrowseAndBorrow;
|
|
131
|
-
iaBookActions.bwbPurchaseUrl = '';
|
|
132
|
-
iaBookActions.modalConfig = modalConfig;
|
|
133
|
-
iaBookActions.lendingBarPostInit = lendingBarPostInit;
|
|
134
|
-
iaBookActions.tokenDelay = 2000; // 2 seconds
|
|
135
|
-
iaBookActions.returnUrl = 'https://openlibrary.org';
|
|
136
|
-
|
|
137
|
-
let lendingStatus1 = iaBookActions.lendingStatus;
|
|
138
|
-
|
|
139
|
-
const manifest = await fetch('https://ia801302.us.archive.org/BookReader/BookReaderJSIA.php?id=goody&itemPath=/29/items/goody&server=ia801302.us.archive.org&format=jsonp&subPrefix=goody&requestUri=/details/goody/mode/1up%3Fview%3Dtheater%26ui%3Dembed%26wrapper%3Dfalse');
|
|
140
|
-
|
|
141
|
-
console.log('manifest ****', manifest).then(res => res.json());
|
|
142
|
-
</script>
|
|
143
|
-
|
|
144
|
-
</div>
|
|
145
|
-
</body>
|
|
146
|
-
</html>
|