@internetarchive/ia-book-actions 0.0.6-8 → 0.0.6-9

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 CHANGED
@@ -72,14 +72,16 @@
72
72
  margin: 2px;
73
73
  }
74
74
 
75
- #ui-overlay {
76
- position: fixed;
77
- top: 0;
78
- left: 0;
79
- width: 100%;
80
- height: 100%;
81
- background: black;
82
- opacity: 0.3;
75
+ body.modal-manager-open {
76
+ overflow: hidden;
77
+ }
78
+
79
+ modal-manager {
80
+ display: none;
81
+ }
82
+
83
+ modal-manager[mode='open'] {
84
+ display: block;
83
85
  }
84
86
  </style>
85
87
  </head>
@@ -95,6 +97,7 @@
95
97
  defaultLendingStatus,
96
98
  canBrowseAndBorrow,
97
99
  } from '../src/assets/data/lending-get-status-service.js';
100
+ import { ModalConfig } from '@internetarchive/modal-manager';
98
101
 
99
102
  const userid = '@neeraj-archive';
100
103
  const identifier = 'naturalhistoryof00unse_4111';
@@ -102,13 +105,17 @@
102
105
 
103
106
  let iaBookActions = document.querySelector('ia-book-actions');
104
107
 
108
+ const modalConfig = new ModalConfig();
109
+ modalConfig.headerColor = '#d9534f';
110
+
105
111
  // set defaultLendingStatus for unavailable (without borrowables) book
106
- iaBookActions.userid = '';
112
+ iaBookActions.userid = userid;
107
113
  iaBookActions.identifier = identifier;
108
114
  iaBookActions.bookTitle = 'Contemporary Black biography. Volume 39 : profiles from the interContemporary Black biography. Volume 39';
109
115
  iaBookActions.lendingStatus = canBrowseAndBorrow;
110
116
  iaBookActions.bwbPurchaseUrl = '';
111
117
  iaBookActions.barType = '';
118
+ iaBookActions.modalConfig = modalConfig;
112
119
 
113
120
  let lendingStatus1 = iaBookActions.lendingStatus;
114
121
 
@@ -122,6 +129,29 @@
122
129
  });
123
130
  });
124
131
 
132
+ document.querySelectorAll('.errorEnable input[type=checkbox]').forEach((item) => {
133
+ if (window.location.href.indexOf('?error=true') !== -1) {
134
+ item.checked = true;
135
+ }
136
+ item.addEventListener('click', (e) => {
137
+ var searchParams = new URLSearchParams(window.location.search);
138
+ var separate = '';
139
+ if (e.target.checked) {
140
+ separate = '?';
141
+ searchParams.set('error', true);
142
+ } else {
143
+ separate = '';
144
+ searchParams.delete('error');
145
+ }
146
+
147
+ if (history.pushState) {
148
+ var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + separate + searchParams;
149
+ window.history.pushState({path:newurl},'',newurl);
150
+ }
151
+ });
152
+ });
153
+
154
+
125
155
  document.querySelectorAll('.userState input[type=checkbox]').forEach((item) => {
126
156
  item.addEventListener('click', (e) => {
127
157
  if (e.target.checked) {
@@ -156,7 +186,7 @@
156
186
  if (e.target.value === 'user_has_browsed') {
157
187
  lendingStatus1.user_has_browsed = true;
158
188
  lendingStatus1.available_to_browse = false;
159
- lendingStatus1.secondsLeftOnLoan = 30;
189
+ lendingStatus1.secondsLeftOnLoan = 10;
160
190
  lendingStatus1.browsingExpired = false;
161
191
  } else if(e.target.value === 'browsingExpired') {
162
192
  lendingStatus1.user_has_browsed = true;
@@ -229,6 +259,9 @@
229
259
  <fieldset>
230
260
  <legend>Dev testing for book action bar</legend>
231
261
  <table class="initial">
262
+ <tr colspan='5'>
263
+ <td class="errorEnable"><label><input type="checkbox" name="errorEnable" value="errorEnable" />Do you want to see error response?</label></td>
264
+ </tr>
232
265
  <tr>
233
266
  <td class="userState">
234
267
  <label><input type="checkbox" name="user" value="isAdmin" />isAdmin</label>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/ia-book-actions",
3
- "version": "0.0.6-8",
3
+ "version": "0.0.6-9",
4
4
  "description": "Bookreader actions for borrowable book",
5
5
  "author": "Internet Archive",
6
6
  "license": "AGPL-3.0-only",
@@ -20,8 +20,9 @@
20
20
  "dependencies": {
21
21
  "@internetarchive/ia-icons": "^1.2.2",
22
22
  "@internetarchive/icon-bookmark": "^1.1.3",
23
- "@internetarchive/icon-info": "^1.2.6",
24
23
  "@internetarchive/icon-close": "^1.1.3",
24
+ "@internetarchive/icon-info": "^1.2.6",
25
+ "@internetarchive/modal-manager": "^0.2.1",
25
26
  "@internetarchive/shared-resize-observer": "^0.0.1",
26
27
  "lit-element": "^2.4.0",
27
28
  "lit-html": "^1.3.0"
@@ -27,7 +27,7 @@ export class CollapsibleActionGroup extends ActionsHandler {
27
27
  hasAdminAccess: { type: Boolean },
28
28
  dropdownArrow: { type: String },
29
29
  disabled: { type: Boolean },
30
- bookHasBrowsed: { type: Boolean },
30
+ borrowType: { type: String },
31
31
  };
32
32
  }
33
33
 
@@ -46,13 +46,8 @@ export class CollapsibleActionGroup extends ActionsHandler {
46
46
  this.title = '';
47
47
  this.loaderIcon = 'https://archive.org/upload/images/tree/loading.gif';
48
48
  this.disabled = false;
49
- this.bookHasBrowsed = false;
50
- }
51
-
52
- firstUpdated() {
53
- if (this.bookHasBrowsed) {
54
- this.emitFetchLoanToken();
55
- }
49
+ this.borrowType = ''; // (browsed|borrowed)
50
+ this.consecutiveLoanCounts = 1; // consecutive loan count
56
51
  }
57
52
 
58
53
  updated(changed) {
@@ -62,19 +57,31 @@ export class CollapsibleActionGroup extends ActionsHandler {
62
57
  }
63
58
  }
64
59
 
65
- // this is execute on demo page only
66
- if (changed.has('bookHasBrowsed')) {
67
- this.emitFetchLoanToken();
60
+ // this is execute to fetch loan token
61
+ if (changed.has('borrowType')) {
62
+ this.emitEnableBookAccess();
68
63
  }
69
64
  }
70
65
 
71
66
  /* emit custom event to fetch loan token */
72
- emitFetchLoanToken() {
67
+ emitEnableBookAccess() {
68
+ // send consecutiveLoanCounts for browsed books only.
69
+ // for borrowed books, we just send [Counts-1]
70
+ if (this.borrowType === 'browsed') {
71
+ this.consecutiveLoanCounts =
72
+ localStorage.getItem('consecutive-loan-count') ?? 1;
73
+ }
74
+
73
75
  this.dispatchEvent(
74
- new CustomEvent('fetchLoanToken', {
76
+ new CustomEvent('enableBookAccess', {
75
77
  detail: {
76
- event: { category: 'action' },
77
- bookHasBrowsed: this.bookHasBrowsed,
78
+ event: {
79
+ category: `${this.borrowType}BookAccess`, // browsedBookAccess | borrowedBookAccess
80
+ action: `${
81
+ this.borrowType === 'browsed' ? 'BrowseCounts-' : 'Counts-'
82
+ }${this.consecutiveLoanCounts}`, // (BrowseCounts-1|Counts-X)
83
+ },
84
+ borrowType: this.borrowType,
78
85
  },
79
86
  })
80
87
  );
@@ -29,19 +29,32 @@ export default function ActionsHandlerService(options) {
29
29
  body: formData,
30
30
  })
31
31
  .then(response => {
32
- // test changes, (won't affect you)
33
- if (baseHost == '/demo/1' || baseHost == '/demo/') {
34
- if (option.action == 'create_token') {
35
- // return {'success': false, 'error': 'loan token not found. please try again later.',};
36
- return {
37
- success: true,
38
- token: '1640945898-f77a0cb615190798f1faf2dafe277b2e',
39
- };
40
- }
32
+ let shouldReturnError =
33
+ window.location.href.indexOf('?error=true') !== -1;
34
+ const tokenError = 'loan token not found. please try again later.';
35
+ const borrowError =
36
+ 'This book is not available to borrow at this time. Please try again later.';
37
+
38
+ // return error reponse if query param has ?error=true param...
39
+ if (option.action == 'create_token' && shouldReturnError) {
40
+ return {
41
+ success: false,
42
+ error: tokenError,
43
+ };
44
+ }
41
45
 
46
+ if (shouldReturnError) {
47
+ return {
48
+ status: true,
49
+ error: borrowError,
50
+ };
51
+ }
52
+
53
+ // return success response for /demo/ server...
54
+ if (baseHost == '/demo/1' || baseHost == '/demo/') {
42
55
  return {
43
- error:
44
- 'This book is not available to borrow at this time. Please try again later.',
56
+ success: true,
57
+ message: 'operation executed successfully!',
45
58
  };
46
59
  }
47
60
 
@@ -15,24 +15,37 @@ export default class ActionsHandler extends LitElement {
15
15
  super();
16
16
  this.identifier = identifier;
17
17
  this.ajaxTimeout = 6000;
18
- this.loanTokenPollingDelay = 20000; // 20000 ms = 20 sec
18
+ this.loanTokenPollingDelay =
19
+ window.location.pathname === '/demo/' ? 2000 : 120000; // 120000 ms = 2 min
19
20
  this.loanTokenInterval = null;
20
21
  this.bindEvents();
21
22
  }
22
23
 
24
+ disconnectedCallback() {
25
+ this.loanTokenInterval = undefined;
26
+ }
27
+
23
28
  sendEvent(eventCategory, eventAction) {
24
29
  // eslint-disable-next-line no-console
25
30
  console?.log('Book action: ', { eventCategory, eventAction });
26
- window?.archive_analytics?.send_event(
31
+ window?.archive_analytics?.send_event_no_sampling(
27
32
  eventCategory,
28
33
  eventAction,
29
- window.location.pathname
34
+ `identifier=${this.identifier}`
30
35
  );
31
36
  }
32
37
 
33
38
  bindEvents() {
34
39
  this.addEventListener('browseBook', ({ detail }) => {
35
40
  this.handleBrowseIt();
41
+ this.setConsecutiveLoanCounts();
42
+ const { category, action } = detail.event;
43
+ this.sendEvent(category, action);
44
+ });
45
+
46
+ this.addEventListener('browseBookAgain', ({ detail }) => {
47
+ this.handleBrowseIt();
48
+ this.setConsecutiveLoanCounts('browseAgain');
36
49
  const { category, action } = detail.event;
37
50
  this.sendEvent(category, action);
38
51
  });
@@ -87,16 +100,19 @@ export default class ActionsHandler extends LitElement {
87
100
  this.sendEvent(category, action);
88
101
  });
89
102
 
90
- this.addEventListener('fetchLoanToken', ({ detail }) => {
91
- const bookHasBrowsed = detail?.bookHasBrowsed;
103
+ this.addEventListener('enableBookAccess', ({ detail }) => {
104
+ const borrowType = detail?.borrowType;
92
105
 
93
- // fetch loan token and set an interval
94
- if (bookHasBrowsed) {
106
+ // fetch loan token for browsed/borrowed book and set an interval
107
+ if (borrowType) {
95
108
  console.log('token poll started...');
96
109
 
97
110
  this.loanTokenInterval = setInterval(() => {
98
111
  this.handleLoanTokenPoller();
99
112
  }, this.loanTokenPollingDelay);
113
+
114
+ const { category, action } = detail?.event;
115
+ this.sendEvent(category, action);
100
116
  } else {
101
117
  // if book is not browsed, just clear token polling interval
102
118
  clearInterval(this.loanTokenInterval);
@@ -192,6 +208,7 @@ export default class ActionsHandler extends LitElement {
192
208
  action: context,
193
209
  error: data => {
194
210
  this.ActionError(context, data);
211
+ clearInterval(this.loanTokenInterval); // stop token fetch api
195
212
  },
196
213
  });
197
214
  }
@@ -236,6 +253,23 @@ export default class ActionsHandler extends LitElement {
236
253
  }, this.ajaxTimeout);
237
254
  }
238
255
 
256
+ // save consecutive loan count for borrow
257
+ setConsecutiveLoanCounts(action = '') {
258
+ const { localStorage } = window;
259
+ if (localStorage) {
260
+ let newCount = 1;
261
+ const storageKey = `consecutive-loan-count`;
262
+ const existingCount = Number(localStorage.getItem(storageKey));
263
+
264
+ // want to increase browse-count by 1 if,
265
+ // you consecutive reading a book.
266
+ if (action === 'browseAgain') {
267
+ newCount = existingCount ? existingCount + 1 : 1;
268
+ }
269
+ localStorage.setItem(storageKey, newCount);
270
+ }
271
+ }
272
+
239
273
  deleteLoanCookies() {
240
274
  const date = new Date();
241
275
  date.setTime(date.getTime() - 24 * 60 * 60 * 1000); // one day ago
@@ -75,7 +75,9 @@ export default class GetLendingActions {
75
75
  const disableBorrow = lendingStatus.loanCount >= lendingStatus.maxLoans;
76
76
 
77
77
  let primaryTitleText = '';
78
- if (lendingStatus.user_has_browsed) {
78
+ let isBrowsed =
79
+ lendingStatus.user_has_browsed && !lendingStatus.browsingExpired;
80
+ if (isBrowsed) {
79
81
  primaryTitleText = this.getBrowseCountdownTitle();
80
82
  } else {
81
83
  primaryTitleText = `Your loan of this book has ${lendingStatus.daysLeftOnLoan} days left.`;
@@ -94,6 +96,7 @@ export default class GetLendingActions {
94
96
  this.actionsConfig.adminAccessConfig(),
95
97
  this.actionsConfig.purchaseConfig(),
96
98
  ],
99
+ borrowType: isBrowsed ? 'browsed' : 'borrowed',
97
100
  };
98
101
  }
99
102
 
@@ -2,12 +2,12 @@
2
2
  import { html, css, LitElement } from 'lit-element';
3
3
 
4
4
  import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
5
+ import { ModalConfig } from '@internetarchive/modal-manager';
5
6
 
6
7
  import './components/collapsible-action-group.js';
7
8
  import './components/book-title-bar.js';
8
9
  import './components/text-group.js';
9
10
  import './components/info-icon.js';
10
- import './components/dialog-alert.js';
11
11
 
12
12
  import GetLendingActions from './core/services/get-lending-actions.js';
13
13
  import { mobileContainerWidth } from './core/config/constants.js';
@@ -23,9 +23,8 @@ export default class IABookActions extends LitElement {
23
23
  bwbPurchaseUrl: { type: String },
24
24
  barType: { type: String },
25
25
  sharedObserver: { attribute: false },
26
- disable: { type: Boolean },
27
- dialogVisible: { type: Boolean },
28
- bookHasBrowsed: { type: Boolean },
26
+ disableActionGroup: { type: Boolean },
27
+ modalConfig: { type: Object },
29
28
  };
30
29
  }
31
30
 
@@ -45,8 +44,7 @@ export default class IABookActions extends LitElement {
45
44
  this.secondaryActions = [];
46
45
  this.lendingOptions = {};
47
46
  this.disableActionGroup = false;
48
- this.dialogVisible = false;
49
- this.bookHasBrowsed = false;
47
+ this.modalConfig = {};
50
48
  }
51
49
 
52
50
  disconnectedCallback() {
@@ -58,6 +56,11 @@ export default class IABookActions extends LitElement {
58
56
  this.sharedObserver = new SharedResizeObserver();
59
57
  this.setupResizeObserver();
60
58
  }
59
+
60
+ if (!Object.keys(this.modalConfig).length) {
61
+ this.modalConfig = new ModalConfig();
62
+ this.modalConfig.headerColor = '#d9534f';
63
+ }
61
64
  this.setupLendingToolbarActions();
62
65
  }
63
66
 
@@ -146,12 +149,10 @@ export default class IABookActions extends LitElement {
146
149
  return action != null;
147
150
  });
148
151
 
149
- this.bookHasBrowsed =
150
- this.lendingStatus.user_has_browsed &&
151
- !this.lendingStatus.browsingExpired;
152
- if (this.bookHasBrowsed) {
153
- // start timer for 1-hour borrowed book.
154
- // when 1 hour is completed, we shows browse-again button
152
+ this.borrowType = actions.borrowType;
153
+ if (this.borrowType === 'browsed') {
154
+ // start timer for browsed.
155
+ // when browse is completed, we shows browse-again button
155
156
  this.startBrowseTimer();
156
157
  }
157
158
  }
@@ -161,21 +162,9 @@ export default class IABookActions extends LitElement {
161
162
  <section class="lending-wrapper">
162
163
  ${this.barType === 'title' ? this.bookTitleBar : this.bookActionBar}
163
164
  </section>
164
-
165
- <show-dialog
166
- .title=${this.dialogTitle}
167
- .body=${this.dialogBody}
168
- .actions=${this.dialogActions}
169
- ?opened="${this.dialogVisible}"
170
- @dialogAlertClose="${() => this.closeDialogAlert()}"
171
- ></show-dialog>
172
165
  `;
173
166
  }
174
167
 
175
- closeDialogAlert() {
176
- this.dialogVisible = false;
177
- }
178
-
179
168
  get bookTitleBar() {
180
169
  return html`<book-title-bar
181
170
  .identifier=${this.identifier}
@@ -192,9 +181,9 @@ export default class IABookActions extends LitElement {
192
181
  .primaryActions=${this.primaryActions}
193
182
  .secondaryActions=${this.secondaryActions}
194
183
  .width=${this.width}
195
- .hasAdminAccess=${this.hasAdminAccess}
196
- .disabled=${this.disableActionGroup}
197
- .bookHasBrowsed=${this.bookHasBrowsed}
184
+ .borrowType=${this.borrowType}
185
+ ?hasAdminAccess=${this.hasAdminAccess}
186
+ ?disabled=${this.disableActionGroup}
198
187
  @lendingActionError=${this.handleLendingActionError}
199
188
  >
200
189
  </collapsible-action-group>
@@ -202,6 +191,10 @@ export default class IABookActions extends LitElement {
202
191
  `;
203
192
  }
204
193
 
194
+ /*
195
+ * handle lending errors occure on different operation like
196
+ * browse book, borrow book, borrowed book token etc...
197
+ */
205
198
  handleLendingActionError(e) {
206
199
  // toggle activity loader
207
200
  this.disableActionGroup = !this.disableActionGroup;
@@ -209,10 +202,7 @@ export default class IABookActions extends LitElement {
209
202
  const context = e?.detail?.context;
210
203
  const errorMsg = e?.detail?.data?.error;
211
204
 
212
- // early exist if you don't have errorMsg
213
- if (!errorMsg) return;
214
-
215
- this.initializeDialogAlert(context, errorMsg);
205
+ if (errorMsg) this.showErrorModal(context, errorMsg);
216
206
 
217
207
  // update action bar state if book is not available to browse or borrow.
218
208
  if (errorMsg && errorMsg.match(/not available to borrow/gm)) {
@@ -232,22 +222,25 @@ export default class IABookActions extends LitElement {
232
222
  }
233
223
  }
234
224
 
235
- /* set props value to show dialog alert */
236
- initializeDialogAlert(context, errorMsg) {
237
- this.dialogVisible = true;
238
- this.dialogTitle = 'Sorry!';
239
- this.dialogBody = errorMsg;
240
- this.dialogActions = [];
241
-
242
- if (context === 'create_token') {
243
- this.dialogActions = [
244
- {
245
- className: 'ia-button primary',
246
- text: 'Back to Item Details',
247
- href: `/details/${this.lendingStatus.bookUrl}`,
248
- },
249
- ];
225
+ /* show error message if something went wrong */
226
+ async showErrorModal(context, errorMsg) {
227
+ // add modal-manager in DOM to show alert message
228
+ this.modal = document.createElement('modal-manager');
229
+ await document.body.appendChild(this.modal);
230
+
231
+ // fallback if <modal-manager> is not found!
232
+ if (!this.modal) {
233
+ alert(errorMsg);
234
+ return;
250
235
  }
236
+
237
+ this.disableActionGroup = false;
238
+ this.modalConfig.title = 'Sorry!';
239
+ this.modalConfig.message = errorMsg;
240
+
241
+ this.modal.showModal({
242
+ config: this.modalConfig,
243
+ });
251
244
  }
252
245
 
253
246
  get iconClass() {
@@ -1,5 +1,6 @@
1
1
  import { html, fixture, expect } from '@open-wc/testing';
2
2
  import '../../src/components/collapsible-action-group.js';
3
+ import Sinon from 'sinon';
3
4
 
4
5
  const container = ({
5
6
  primaryActions = [
@@ -23,10 +24,12 @@ const container = ({
23
24
  text: 'Purchase',
24
25
  },
25
26
  ],
27
+ borrowType = '',
26
28
  } = {}) =>
27
29
  html`<collapsible-action-group
28
30
  .primaryActions=${primaryActions}
29
31
  .secondaryActions=${secondaryActions}
32
+ .borrowType=${borrowType}
30
33
  ></collapsible-action-group>`;
31
34
 
32
35
  describe('<collapsible-action-group>', () => {
@@ -82,3 +85,27 @@ describe('<collapsible-action-group>', () => {
82
85
  expect(eAnalytics.action).to.equal('Browse');
83
86
  });
84
87
  });
88
+
89
+ describe('fetch loan token and localStorage for browsed/borrowsed book', () => {
90
+ beforeEach(() => {
91
+ const localStorageMock = {
92
+ getItem: Sinon.spy(),
93
+ setItem: Sinon.spy(),
94
+ };
95
+ Object.defineProperty(window, 'localStorage', {
96
+ value: localStorageMock,
97
+ });
98
+ });
99
+
100
+ it('test localStorage function when borrowType is browsed', async () => {
101
+ await fixture(container({ borrowType: 'browsed' }));
102
+ expect(localStorage.getItem).to.be.calledOnce;
103
+ expect(localStorage.getItem).to.be.calledWith('consecutive-loan-count');
104
+ });
105
+
106
+ it('test localStorage function when borrowType is borrowed', async () => {
107
+ await fixture(container({ borrowType: 'borrowed' }));
108
+ expect(localStorage.getItem).to.not.be.calledOnce;
109
+ expect(localStorage.getItem).to.not.be.calledWith('consecutive-loan-count');
110
+ });
111
+ });
@@ -130,7 +130,6 @@ describe('Borrow status actions', () => {
130
130
  el.dispatchEvent(errorEvent);
131
131
  await el.updateComplete;
132
132
 
133
- console.log(el.lendingStatus);
134
133
  // removed available_to_browse from lending bar
135
134
  expect(el.lendingStatus.available_to_browse).to.be.false;
136
135
  expect(el.primaryActions[0].text).to.equal('Borrow for 14 days');
@@ -1,139 +0,0 @@
1
- /* eslint-disable */
2
- import { LitElement, html, css } from 'lit-element';
3
- import { classMap } from 'lit-html/directives/class-map';
4
-
5
- import '@internetarchive/icon-close/icon-close.js';
6
- import buttonBaseStyle from '../assets/styles/ia-button.js';
7
-
8
- export class ShowDialog extends LitElement {
9
- static get properties() {
10
- return {
11
- title: { type: String },
12
- body: { type: String },
13
- actions: { type: Array },
14
- opened: { type: Boolean },
15
- };
16
- }
17
-
18
- constructor() {
19
- super();
20
- this.title = 'Error';
21
- this.body =
22
- 'Unexpected error: loan does not exist. Please try deleting your archive.org cookie.';
23
- this.actions = [];
24
- this.opened = false;
25
- }
26
-
27
- updated(changed) {
28
- if (changed.get('opened') === false) {
29
- this.addOverlay();
30
- } else {
31
- this.removeOverlay();
32
- }
33
- }
34
-
35
- render() {
36
- return html`
37
- <div
38
- class="${classMap({
39
- dialog: true,
40
- opened: this.opened,
41
- closed: !this.opened,
42
- })}"
43
- >
44
- <div class="dialog-head">
45
- ${this.title}
46
- <ia-icon-close
47
- @click="${() =>
48
- this.dispatchEvent(new CustomEvent('dialogAlertClose'))}"
49
- ></ia-icon-close>
50
- </div>
51
- <div class="dialog-body">${this.body}</div>
52
- <div class="dialog-foot">${this.renderActionButton}</div>
53
- </div>
54
- `;
55
- }
56
-
57
- /* exceptional case to use dom element */
58
- addOverlay() {
59
- if (this.opened && !document.getElementById('ui-overlay')) {
60
- const overlayElement = document.createElement('div');
61
- overlayElement.id = 'ui-overlay';
62
- document.getElementsByTagName('body')[0].appendChild(overlayElement);
63
- }
64
- }
65
-
66
- /* exceptional case to use dom element */
67
- removeOverlay() {
68
- const overlayElement = document.getElementById('ui-overlay');
69
- if (overlayElement) overlayElement.remove();
70
- }
71
-
72
- get renderActionButton() {
73
- if (!this.actions) return;
74
-
75
- return this.actions.map(
76
- action =>
77
- html`<a class=${action.className} href=${action.href}>
78
- ${action.text}
79
- </button>`
80
- );
81
- }
82
-
83
- static get styles() {
84
- const dialogStyle = css`
85
- :host {
86
- color: #343434;
87
- font-size: 1.6rem;
88
- }
89
- .dialog {
90
- position: absolute;
91
- background: #fff;
92
- border-radius: 1.2rem;
93
- z-index: 3000;
94
- flex-direction: column;
95
- min-width: 300px;
96
- max-width: 400px;
97
- left: 50%;
98
- transform: translateX(-50%);
99
-
100
- border: 2px solid #ccc;
101
- border-radius: 12px;
102
- box-shadow: 0px 0px 27px 6px rgb(66 66 66 / 80%);
103
- }
104
- .dialog-head,
105
- .dialog-body,
106
- .dialog-foot {
107
- padding: 1rem;
108
- user-select: none;
109
- text-align: left;
110
- }
111
- .dialog-body {
112
- border: 1px solid #d8d8d8;
113
- }
114
- ia-icon-close {
115
- position: absolute;
116
- right: 0.5rem;
117
- top: 0.5rem;
118
- width: 2.5rem;
119
- height: 2.5rem;
120
- vertical-align: middle;
121
- --iconFillColor: #333;
122
- cursor: pointer;
123
- }
124
- .opened {
125
- display: flex;
126
- }
127
- .closed {
128
- display: none;
129
- }
130
- a {
131
- text-decoration: none;
132
- }
133
- `;
134
-
135
- return [buttonBaseStyle, dialogStyle];
136
- }
137
- }
138
-
139
- customElements.define('show-dialog', ShowDialog);