diff --git a/app/components/mobile-dialog.hbs b/app/components/mobile-dialog.hbs new file mode 100644 index 00000000..e8145324 --- /dev/null +++ b/app/components/mobile-dialog.hbs @@ -0,0 +1,12 @@ +{{#if @isDevEnv}} + {{#if @isMobileDevice}} + {{#if this.isDialogVisible}} + + Redirect to RDS App +
+ + +
+ {{/if}} + {{/if}} +{{/if}} diff --git a/app/components/mobile-dialog.js b/app/components/mobile-dialog.js new file mode 100644 index 00000000..23f968c4 --- /dev/null +++ b/app/components/mobile-dialog.js @@ -0,0 +1,52 @@ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import ENV from 'website-my/config/environment'; +import { tracked } from '@glimmer/tracking'; + +export default class MobileDialogComponent extends Component { + @tracked isDialogVisible = true; + + @action + closeDialog() { + this.isDialogVisible = false; + } + + @action + openRDSApp() { + this.openApp(); + } + + openApp() { + let isAppInstalled = false; + const appScheme = ENV.RDS_ANDROID_SCHEME; + const fallbackURL = ENV.ANDROID_GITHUB_URL; + const userAgent = navigator.userAgent || navigator.vendor || window.opera; + const MAXTIME = 1000; + + if (/android/i.test(userAgent)) { + const startTime = Date.now(); + const iframe = document.createElement('iframe'); + iframe.style.display = 'none'; + iframe.src = appScheme; + document.body.appendChild(iframe); + this.isDialogVisible = false; + + window.addEventListener('blur', function () { + document.body.removeChild(iframe); + + const timeTaken = Date.now() - startTime; + if (timeTaken <= MAXTIME) { + isAppInstalled = true; + } + }); + + setTimeout(function () { + if (!isAppInstalled) { + document.body.removeChild(iframe); + window.location.href = fallbackURL; + } + this.isDialogVisible = false; + }, 1000); + } + } +} diff --git a/app/components/self-clear-cache.hbs b/app/components/self-clear-cache.hbs new file mode 100644 index 00000000..fca13aac --- /dev/null +++ b/app/components/self-clear-cache.hbs @@ -0,0 +1,21 @@ +{{#if @dev}} +
+
+ Last Request: {{@time}} +
+ +
+ {{@totalTimes}} + / 3 requests remaining for today +
+
+{{/if}} \ No newline at end of file diff --git a/app/constants/self-clear-cache.js b/app/constants/self-clear-cache.js new file mode 100644 index 00000000..64068cc0 --- /dev/null +++ b/app/constants/self-clear-cache.js @@ -0,0 +1,3 @@ +export const MAX_CACHE_PURGE_COUNT = 3; +// this will be removed once we fetch this from the API +export const LAST_UPDATED_REQUEST = '24 November, 1:23 PM IST'; diff --git a/app/controllers/application.js b/app/controllers/application.js index fbde4ec2..a6d408b5 100644 --- a/app/controllers/application.js +++ b/app/controllers/application.js @@ -1,5 +1,6 @@ import Controller from '@ember/controller'; import { inject as service } from '@ember/service'; +import { tracked } from '@glimmer/tracking'; import { MAIN_SITE_URL } from '../constants/url'; import { action } from '@ember/object'; import { GITHUB_URL } from '../constants/url'; @@ -7,12 +8,20 @@ import ENV from 'website-my/config/environment'; export default class ApplicationController extends Controller { @service router; + @service featureFlag; + @service toast; + @tracked isMobileDevice = this.detectMobileDevice(); + GITHUB_URL = GITHUB_URL; BASE_API_URL = ENV.BASE_API_URL; get canShowNavBar() { return this.router.currentRouteName != 'signup'; } + get isDevMode() { + return this.featureFlag.isDevMode; + } + @action async signOutHandler() { try { const response = await fetch(`${this.BASE_API_URL}/auth/signout`, { @@ -25,6 +34,21 @@ export default class ApplicationController extends Controller { } } catch (err) { console.error('Error: ', err); + this.toast.error( + 'Unable to sign out. Something went wrong. Please try again.' + ); + } + } + + detectMobileDevice() { + let regexp = /android|iphone|kindle|ipad/i; + let details = navigator.userAgent; + let isMobileDevice = regexp.test(details); + + if (isMobileDevice) { + return true; + } else { + return false; } } } diff --git a/app/controllers/index.js b/app/controllers/index.js index 42ef5e5e..dbd87934 100644 --- a/app/controllers/index.js +++ b/app/controllers/index.js @@ -5,20 +5,32 @@ import ENV from 'website-my/config/environment'; import { inject as service } from '@ember/service'; import { toastNotificationTimeoutOptions } from '../constants/toast-notification'; import { USER_STATES } from '../constants/user-status'; +import { + MAX_CACHE_PURGE_COUNT, + LAST_UPDATED_REQUEST, +} from '../constants/self-clear-cache'; const BASE_URL = ENV.BASE_API_URL; export default class IndexController extends Controller { + @service featureFlag; @service toast; @tracked status = this.model; @tracked isStatusUpdating = false; @tracked showUserStateModal = false; @tracked newStatus; + @tracked isPurgingCache = false; + @tracked cacheTriggeredPending = MAX_CACHE_PURGE_COUNT; + lastUpdatedCacheRequest = LAST_UPDATED_REQUEST; @action toggleUserStateModal() { this.showUserStateModal = !this.showUserStateModal; } + get isDevMode() { + return this.featureFlag.isDevMode; + } + @action async updateStatus(newStatus) { this.isStatusUpdating = true; if (!('cancelOoo' in newStatus)) { @@ -68,4 +80,37 @@ export default class IndexController extends Controller { this.newStatus = status; this.toggleUserStateModal(); } + + @action async purgeCache() { + this.isPurgingCache = true; + try { + const response = await fetch(`${BASE_URL}/cache`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + credentials: 'include', + }); + if (response.ok) { + const data = await response.json(); + this.cacheTriggeredPending--; + this.toast.success(data.message, '', toastNotificationTimeoutOptions); + } else { + this.toast.error( + 'Something went wrong.', + '', + toastNotificationTimeoutOptions + ); + } + } catch (error) { + console.error('Error : ', error); + this.toast.error( + 'Something went wrong.', + '', + toastNotificationTimeoutOptions + ); + } finally { + this.isPurgingCache = false; + } + } } diff --git a/app/styles/app.css b/app/styles/app.css index d5bdce8b..0772d1f0 100644 --- a/app/styles/app.css +++ b/app/styles/app.css @@ -19,6 +19,8 @@ @import 'qrcode.css'; @import 'progress-bar.css'; @import 'mobile.css'; +@import 'components/mobile-dialog.css'; +@import 'self-clear-cache.css'; html, body { diff --git a/app/styles/components/mobile-dialog.css b/app/styles/components/mobile-dialog.css new file mode 100644 index 00000000..901d7483 --- /dev/null +++ b/app/styles/components/mobile-dialog.css @@ -0,0 +1,30 @@ +.mobile-dialog { + display: block; + border-radius: 4px; + padding: 0.5rem 1rem; + font-weight: 900; + margin: 0 auto; + font-size:large; + text-align: center; + background-color: var(--form--bg); + border: none; + box-shadow: 4px 8px 8px var(--mobile-dialog-box-shadow); + & button { + padding: 0.5rem 1rem; + margin: 1rem; + font-size:medium; + border: none; + border-radius: 4px; + color: var(--body-bg-color); + font-weight: 600; + } + } + + #mobile-dialog__open-button { + background-color: var(--mobile-dialog--open-button); + } + + #mobile-dialog__close-button { + background-color: var(--body-bg-color); + color: var(--landing-page--main-heading); + } \ No newline at end of file diff --git a/app/styles/self-clear-cache.css b/app/styles/self-clear-cache.css new file mode 100644 index 00000000..ec190bc3 --- /dev/null +++ b/app/styles/self-clear-cache.css @@ -0,0 +1,35 @@ +.cache { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin: auto; + box-shadow: 5px 10px 15px #09113344; + border-radius: 10px; + padding: 30px; + font-weight: 700; +} + +.cache__last-request { + padding: 40px 4px 20px; + color: #1d1283; + font-size: 2rem; + text-align: center; +} + +.cache__clear-btn { + border-radius: 10px; + padding: 16px 60px; + border: 3px solid #e49504; + color: #e49504; + background-color: white; + font-weight: 700; + font-size: 1.25rem; + cursor: pointer; +} + +.cache__remaining-requests { + padding-top: 30px; + color: #1d1283; + font-size: 1.25rem; +} diff --git a/app/styles/variables.css b/app/styles/variables.css index 189a8b96..d6032861 100644 --- a/app/styles/variables.css +++ b/app/styles/variables.css @@ -181,4 +181,7 @@ --profile-edit-btn-clr: #1e429f; --profile-disabled-btn-bg-clr: #e5efeb; --profile-disabled-btn-text-clr: #9ca3af; + + --mobile-dialog-box-shadow: hsl(0deg 0% 0% / 0.38); + --mobile-dialog--open-button: #1d1283; } diff --git a/app/templates/application.hbs b/app/templates/application.hbs index 2701d40d..1d062460 100644 --- a/app/templates/application.hbs +++ b/app/templates/application.hbs @@ -1,5 +1,9 @@ {{page-title "My | Real Dev Squad"}} +
- {{outlet}} + {{outlet}}
\ No newline at end of file diff --git a/app/templates/index.hbs b/app/templates/index.hbs index c377e590..7282738e 100644 --- a/app/templates/index.hbs +++ b/app/templates/index.hbs @@ -1,8 +1,15 @@ -
+

Welcome to my site!

- +`); + + assert.dom('[data-test-mobile-dialog]').doesNotExist(); + }); + + test('Mobile-Dialog should renders', async function (assert) { + this.setProperties({ + isDevEnv: true, + isMobileDevice: true, + }); + + await render( + hbs`` + ); + + assert.dom('[data-test-mobile-dialog]').exists(); + }); +}); diff --git a/tests/integration/components/self-clear-cache-test.js b/tests/integration/components/self-clear-cache-test.js new file mode 100644 index 00000000..0bf00945 --- /dev/null +++ b/tests/integration/components/self-clear-cache-test.js @@ -0,0 +1,36 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | self-clear-cache', function (hooks) { + setupRenderingTest(hooks); + + test('should render the component with relevant details', async function (assert) { + this.setProperties({ + purgeCache: () => {}, + cacheTriggeredPending: 3, + isDevMode: true, + isPurgingCache: false, + lastUpdatedCacheRequest: '24 November, 1:23 PM IST', + }); + + await render(hbs` + + `); + + assert + .dom('[data-test-pending-requests]') + .hasText(`3 / 3 requests remaining for today`); + assert.dom('[data-test-btn-clear-cache]').hasText('Clear Cache'); + assert + .dom('[data-test-last-time]') + .hasText('Last Request: 24 November, 1:23 PM IST'); + }); +});