Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MWPW-153363] Countdown Timer - CDT #2803

Closed
wants to merge 42 commits into from
Closed
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
24b9d01
add block placeholder
rahulgupta999 Aug 19, 2024
934a565
Add default func
rahulgupta999 Aug 19, 2024
2089792
Add CDT LIT component
rahulgupta999 Aug 28, 2024
6960b74
Fix CDT bug
rahulgupta999 Aug 28, 2024
31ad9e7
Add some basic styling
rahulgupta999 Aug 28, 2024
15dd05a
some styling
rahulgupta999 Aug 29, 2024
cc47eb3
Styling fixes
rahulgupta999 Aug 29, 2024
424ed9d
Add cdt
rahulgupta999 Aug 29, 2024
aded0d3
Lint fixes
rahulgupta999 Aug 29, 2024
701db3e
cr comments
rahulgupta999 Aug 29, 2024
3735250
review comment
rahulgupta999 Aug 29, 2024
06f69df
RC
rahulgupta999 Aug 29, 2024
a747963
RC
rahulgupta999 Aug 29, 2024
148e00b
Link CDT to marquee
rahulgupta999 Aug 30, 2024
0c4fbfd
added light/dark support
rahulgupta999 Aug 30, 2024
ab3b7f3
added div ids
rahulgupta999 Aug 30, 2024
3034ebc
fix unit test
rahulgupta999 Aug 30, 2024
53c29c3
fix
rahulgupta999 Aug 30, 2024
c883f7f
Fix UT
rahulgupta999 Aug 30, 2024
6251807
Fix css
rahulgupta999 Aug 30, 2024
8ea26ff
Add a CDT unit test
rahulgupta999 Aug 30, 2024
07f89a7
Block UTC for CDT
rahulgupta999 Sep 2, 2024
8878e09
updated for ccov
rahulgupta999 Sep 2, 2024
79b6ba7
Update marquee.test.js
rahulgupta999 Sep 2, 2024
8445147
Review comment, remove async
rahulgupta999 Sep 2, 2024
e5f3f23
Hide the CDT till it is ready
rahulgupta999 Sep 2, 2024
5106084
Update marquee.js
rahulgupta999 Sep 2, 2024
3d9d4b5
Merge remote-tracking branch 'upstream/stage' into cdt
rahulgupta999 Sep 2, 2024
ac34c8c
Move from LIT to HTML Element
rahulgupta999 Sep 5, 2024
9ea687f
Fix linting
rahulgupta999 Sep 5, 2024
ed8f705
Add test for coverage
rahulgupta999 Sep 5, 2024
559282a
code coverage
rahulgupta999 Sep 5, 2024
683b210
Fix unit tests
rahulgupta999 Sep 6, 2024
127dcc4
code coverage complete
rahulgupta999 Sep 6, 2024
264e7ef
move styles in the block,
rahulgupta999 Sep 6, 2024
4a2ea64
Add exception for date.parse
rahulgupta999 Sep 6, 2024
9b7d305
Support of CDT for modal
rahulgupta999 Sep 6, 2024
104abd8
add testcase for media
rahulgupta999 Sep 6, 2024
4e1cd96
unused code
rahulgupta999 Sep 6, 2024
bda37e8
fix for vertical layout in marquee
rahulgupta999 Sep 7, 2024
a768246
Merge remote-tracking branch 'upstream/stage' into cdt
rahulgupta999 Sep 9, 2024
bf6a427
CSS fixes for marquee centre
rahulgupta999 Sep 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
37 changes: 37 additions & 0 deletions libs/blocks/countdown-timer/countdown-timer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2024 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
rahulgupta999 marked this conversation as resolved.
Show resolved Hide resolved

import { createTag } from '../../utils/utils.js';
import '../../deps/mas/countdown-timer.js';

export default function init(el) {
const styles = [...el.classList];
const firstLevelDivs = el.querySelectorAll(':scope > div');

// Extract 'DAYS HOURS MINS' from the first div's first child
const daysHoursMins = firstLevelDivs[0].querySelector(':scope > div').textContent.trim();

// Extract 'ENDS IN' from the first div's second child
const cdtLabel = firstLevelDivs[0].querySelector(':scope > div:nth-child(2)').textContent.trim();

// Extract the time ranges from the second and third divs
const timeRanges = Array.from(firstLevelDivs)
.slice(1) // Skip the first div, as it's not part of the time ranges
.flatMap((div) => Array.from(div.querySelectorAll(':scope > div')).map((innerDiv) => Date.parse(innerDiv.textContent.trim()))) // Extract the text content of each inner div
rahulgupta999 marked this conversation as resolved.
Show resolved Hide resolved
.join(','); // Join the array into a comma-separated string

const cdt = createTag('countdown-timer', { class: styles.join(' ') });
rahulgupta999 marked this conversation as resolved.
Show resolved Hide resolved
cdt.setAttribute('label', cdtLabel);
cdt.setAttribute('daysHoursMins', daysHoursMins);
cdt.setAttribute('timeRanges', timeRanges);
el.replaceWith(cdt);
}
105 changes: 105 additions & 0 deletions libs/deps/mas/countdown-timer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import{LitElement as d,html as o}from"/libs/deps/lit-all.min.js";import{css as a}from"/libs/deps/lit-all.min.js";var r=a`
.countdown-timer.horizontal {
display: flex;
flex-direction: row;
align-items: center;
padding: 20px;
border-radius: 10px;
}

.countdown-timer.vertical {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
border-radius: 10px;
}

.countdown-timer.horizontal > div.timer-label {
font-size: 16px;
font-weight: bold;
text-align: center;
font-color: #FFFFFF;
height: 27px;
align-self: center;
margin: 0px 2px 27px 2px;
}

.countdown-timer.vertical > div.timer-label {
font-size: 16px;
font-weight: bold;
text-align: center;
font-color: #FFFFFF;
height: 27px;
align-self: flex-start;
}

.countdown-timer.vertical > div.timer-container-parent {
display: flex;
align-self: flex-start;
}

.countdown-timer.horizontal > div.timer-container-parent {
display: flex;
margin-left: 10px;
}

.timer-container {
display: flex;
flex-direction: column;
align-items: center;
}

.timer-box {
background-color: #EBEBEB;
color: #1D1D1D;
padding: 0px 9px;
border-radius: 5px;
font-size: 18px;
font-weight: bold;
text-align: center;
}

.timer-unit-container {
display: flex;
flex-direction: row;
column-gap: 2px;
align-items: center;
}

.timer-unit-label {
width: 100%;
font-size: 14px;
font-weight: regular;
font-color: #D1D1D1;
text-align: left;
}
`;var e=class extends d{static properties={label:{type:String},daysHoursMins:{type:String},timeRanges:{type:String},daysLeft:{type:String},hoursLeft:{type:String},minutesLeft:{type:String},isVisible:{type:Boolean}};#t=[];#i=[];static styles=[r];constructor(t){super(),this.label="",this.daysHoursMins="",this.timeRanges="",this.daysLeft="",this.hoursLeft="",this.minutesLeft="",this.isVisible=!1}firstUpdated(){this.#t=this.daysHoursMins.split(" "),this.#i=this.timeRanges.split(","),this.countdownStart()}disconnectedCallback(){super.disconnectedCallback(),clearInterval(this.countdownInterval)}countdownCompleted(){this.isVisible=!1,clearInterval(this.countdownInterval)}countdownStart(){this.countdownUpdate(),this.countdownInterval=setInterval(()=>{this.countdownUpdate()},6e4)}countdownUpdate(){let t=Date.now();for(let i=0;i<this.#i.length;i+=2){let l=this.#i[i],n=this.#i[i+1];if(t>=l&&t<=n){this.isVisible=!0;let s=n-t;this.daysLeft=Math.floor(s/(1e3*60*60*24)),this.hoursLeft=Math.floor(s%(1e3*60*60*24)/(1e3*60*60)),this.minutesLeft=Math.floor(s%(1e3*60*60)/(1e3*60)),this.requestUpdate();return}}this.countdownCompleted(),this.requestUpdate()}render(){return this.isVisible?o`
<div class="${this.classList}">
<div class="timer-label">${this.label}</div>
<div class="timer-container-parent">
<div class="timer-container">
<div class="timer-unit-container">
<div class="timer-box">${Math.floor(this.daysLeft/10)}</div>
<div class="timer-box">${this.daysLeft%10}</div>
</div>
<div class="timer-unit-label">${this.#t[0]}</div>
</div>
<div class="timer-label">:</div>
<div class="timer-container">
<div class="timer-unit-container">
<div class="timer-box">${Math.floor(this.hoursLeft/10)}</div>
<div class="timer-box">${this.hoursLeft%10}</div>
</div>
<div class="timer-unit-label">${this.#t[1]}</div>
</div>
<div class="timer-label">:</div>
<div class="timer-container">
<div class="timer-unit-container">
<div class="timer-box">${Math.floor(this.minutesLeft/10)}</div>
<div class="timer-box">${this.minutesLeft%10}</div>
</div>
<div class="timer-unit-label">${this.#t[2]}</div>
</div>
</div>
</div>`:o``}lpad(t,i){return("0"+t).slice(i)}};customElements.define("countdown-timer",e);export{e as default};
9 changes: 9 additions & 0 deletions libs/features/mas/web-components/build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ Promise.all([
plugins: [rewriteImports()],
external: ['lit'],
}),
build({
entryPoints: ['./src/cdt/countdown-timer.js'],
bundle: true,
minify: true,
rahulgupta999 marked this conversation as resolved.
Show resolved Hide resolved
outfile: `${outfolder}/countdown-timer.js`,
format: 'esm',
plugins: [rewriteImports()],
external: ['lit'],
}),
buildLitComponent('merch-icon'),
buildLitComponent('merch-quantity-select'),
buildLitComponent('merch-secure-transaction'),
Expand Down
86 changes: 86 additions & 0 deletions libs/features/mas/web-components/src/cdt/countdown-timer.css.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { css, unsafeCSS } from 'lit';
rahulgupta999 marked this conversation as resolved.
Show resolved Hide resolved
import {
DESKTOP_UP,
LARGE_DESKTOP,
TABLET_UP,
MOBILE_LANDSCAPE,
TABLET_DOWN,
} from '../media.js';

export const styles = css`
.countdown-timer.horizontal {
rahulgupta999 marked this conversation as resolved.
Show resolved Hide resolved
display: flex;
flex-direction: row;
align-items: center;
padding: 20px;
border-radius: 10px;
}

.countdown-timer.vertical {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
border-radius: 10px;
}

.countdown-timer.horizontal > div.timer-label {
font-size: 16px;
font-weight: bold;
text-align: center;
font-color: #FFFFFF;
height: 27px;
align-self: center;
margin: 0px 2px 27px 2px;
}

.countdown-timer.vertical > div.timer-label {
font-size: 16px;
font-weight: bold;
text-align: center;
font-color: #FFFFFF;
height: 27px;
align-self: flex-start;
}

.countdown-timer.vertical > div.timer-container-parent {
display: flex;
align-self: flex-start;
}

.countdown-timer.horizontal > div.timer-container-parent {
display: flex;
margin-left: 10px;
}

.timer-container {
display: flex;
flex-direction: column;
align-items: center;
}

.timer-box {
background-color: #EBEBEB;
color: #1D1D1D;
padding: 0px 9px;
border-radius: 5px;
font-size: 18px;
font-weight: bold;
text-align: center;
}

.timer-unit-container {
display: flex;
flex-direction: row;
column-gap: 2px;
align-items: center;
}

.timer-unit-label {
width: 100%;
font-size: 14px;
font-weight: regular;
font-color: #D1D1D1;
text-align: left;
}
`;
119 changes: 119 additions & 0 deletions libs/features/mas/web-components/src/cdt/countdown-timer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { LitElement, html, css } from 'lit';
import { styles } from './countdown-timer.css.js';

export default class CountdownTimer extends LitElement {
static properties = {
label: { type: String },
daysHoursMins: { type: String },
timeRanges: { type: String },
daysLeft: { type: String },
hoursLeft: { type: String },
minutesLeft: { type: String },
isVisible: {type: Boolean},
};

#timeWords = [];
#timeRangesEpoch = [];

static styles = [styles];

constructor(endDateTime) {
super();
this.label = '';
this.daysHoursMins = '';
this.timeRanges = '';
this.daysLeft = '';
this.hoursLeft = '';
this.minutesLeft = '';
this.isVisible = false;
}

firstUpdated() {
this.#timeWords = this.daysHoursMins.split(' ');
this.#timeRangesEpoch = this.timeRanges.split(',');
this.countdownStart();
}

disconnectedCallback() {
super.disconnectedCallback();
clearInterval(this.countdownInterval);
}

countdownCompleted() {
this.isVisible = false;
clearInterval(this.countdownInterval);
}

countdownStart() {
this.countdownUpdate();
this.countdownInterval = setInterval(() => {
this.countdownUpdate();
}, 60000);
rahulgupta999 marked this conversation as resolved.
Show resolved Hide resolved
}

countdownUpdate() {

let currentTime = Date.now();
//find the time range where the current time is between the start and end time
for (let i = 0; i < this.#timeRangesEpoch.length; i += 2) {
const startTime = this.#timeRangesEpoch[i];
const endTime = this.#timeRangesEpoch[i + 1];

if (currentTime >= startTime && currentTime <= endTime) {
this.isVisible = true;
let diffTime = endTime - currentTime;
this.daysLeft = Math.floor(diffTime / (1000 * 60 * 60 * 24));
this.hoursLeft = Math.floor((diffTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
this.minutesLeft = Math.floor((diffTime % (1000 * 60 * 60)) / (1000 * 60));
this.requestUpdate();
rahulgupta999 marked this conversation as resolved.
Show resolved Hide resolved
return;
}
}

//if the current time is not in any of the time ranges, the countdown is completed
this.countdownCompleted();
this.requestUpdate();
}

render() {
if (!this.isVisible) {
return html``;
} else {
return html`
<div class="${this.classList}">
<div class="timer-label">${this.label}</div>
rahulgupta999 marked this conversation as resolved.
Show resolved Hide resolved
<div class="timer-container-parent">
<div class="timer-container">
<div class="timer-unit-container">
<div class="timer-box">${Math.floor(this.daysLeft/10)}</div>
<div class="timer-box">${this.daysLeft%10}</div>
</div>
<div class="timer-unit-label">${this.#timeWords[0]}</div>
</div>
<div class="timer-label">:</div>
<div class="timer-container">
<div class="timer-unit-container">
<div class="timer-box">${Math.floor(this.hoursLeft/10)}</div>
<div class="timer-box">${this.hoursLeft%10}</div>
</div>
<div class="timer-unit-label">${this.#timeWords[1]}</div>
</div>
<div class="timer-label">:</div>
<div class="timer-container">
<div class="timer-unit-container">
<div class="timer-box">${Math.floor(this.minutesLeft/10)}</div>
<div class="timer-box">${this.minutesLeft%10}</div>
</div>
<div class="timer-unit-label">${this.#timeWords[2]}</div>
</div>
</div>
</div>`;
}
}

lpad(input, length) {
rahulgupta999 marked this conversation as resolved.
Show resolved Hide resolved
return ('0' + input).slice(length);
}
}

customElements.define('countdown-timer', CountdownTimer);
1 change: 1 addition & 0 deletions libs/features/mas/web-components/src/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './merch-card.js';
export * from './merch-card-collection.js';
export * from './cdt/countdown-timer.js';
1 change: 1 addition & 0 deletions libs/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const MILO_BLOCKS = [
'carousel',
'chart',
'columns',
'countdown-timer',
'editorial-card',
'faas',
'featured-article',
Expand Down
Loading