├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Readme.md ├── app.js ├── images ├── blog.png ├── github.png ├── icons │ ├── android-chrome-192x192.png │ ├── android-chrome-384x384.png │ ├── apple-touch-icon-114x114.png │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-144x144.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-180x180.png │ ├── apple-touch-icon-57x57.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-72x72.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── mstile-144x144.png │ ├── mstile-150x150.png │ └── mstile-70x70.png ├── twitter.png └── youtube.png ├── index.html ├── main.css ├── manifest.json ├── serviceWorker.js └── social ├── landing.png └── landing2.png /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [atapas] 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | - Demonstrating empathy and kindness toward other people 21 | - Being respectful of differing opinions, viewpoints, and experiences 22 | - Giving and gracefully accepting constructive feedback 23 | - Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | - Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | - The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | - Trolling, insulting or derogatory comments, and personal or political attacks 33 | - Public or private harassment 34 | - Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | - Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | tapas.adhikary@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Tapas Adhikary 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 2 | # 🤝 Introducing `PromiViz` 3 |

Visualize the JavaScript Promise APIs and learn. It is a playground to learn about promises faster than ever! A tool built for developers by a developer.

4 |

5 | View Demo 6 | · 7 | Learn 8 | . 9 | Report Bug 10 | · 11 | Request Feature 12 |

13 | 14 |

15 | 16 |

17 | 18 | `PromiViz` is an open-source tool to visualize the JavaScript Promise APIs. It is a playground for developers to configure promises with delays, resolve/reject, and more. 19 | 20 | # 🚀 Demo 21 | Here is a quick demo of the app. I hope you enjoy it. 22 | 23 | > [The Demo Link](https://www.youtube.com/watch?v=webs_tRKIIg) 24 | 25 | Liked it? Please give a ⭐️ to PromiViz to grow 💪 stronger. 26 | 27 | ## Many Thanks to all the `Stargazers` who have supported this project with stars(⭐) 28 | 29 | [![Thanks to all stargazers](https://git-lister.onrender.com/api/stars/atapas/promiviz?limit=15)](https://github.com/atapas/promiviz/stargazers) 30 | 31 | 32 | # 💻 Use PromiViz 33 | Please access PromiViz using the URL: 34 | 35 | > https://promiviz.vercel.app/ 36 | 37 | # 🔥 Features 38 | `PromiViz` comes with a bundle of features already. You can do the following with it: 39 | 40 | - Schedule a promise to resolve/reject after a delay. 41 | - Reject a promise specifically. 42 | - Run and test all the Promise APIs, `all`, `any`, `allSettled`, `race`, `resolve`, `reject`. 43 | - Show logs of the execution of the promises. The log includes time, text, and emojis to indicate the status of the promise. 44 | - Ability to retain the logs for a session. 45 | - Ability to clear the logs. 46 | - Ability to set themes. 47 | - Responsive and mobile-friendly. 48 | - It is a PWA(Progressive Web App). 49 | 50 | # How is it helpful to you? 51 | JavaScript promises are a bit of a complex topic to understand for beginners. However your interviewers will love to ask questions about this topic. Hence an in-depth understanding 52 | of how it works internally would be a great advantage. 53 | 54 | `PromiViz` will help you with that. You can run the promises, customize them, and see the execution 55 | logs to understand what's happening. You can also modify the settings, try different combinations of the APIs, resolve/reject to firm up your understanding. 56 | 57 | # 🦄 What are the future enhancements? 58 | Here are some of the future enhancements planned: 59 | - Schedule a promise to resolve/reject after a delay with a custom message. 60 | - Ability to add more promises (beyond the three out-of-the-boxes). 61 | - Ability to run customized examples from the app. 62 | - Ability to run the promises in a loop to showcase the loop-related use-cases. 63 | - Persist a history of promise runs. 64 | - Persist logs across sessions. 65 | - More themes. 66 | # 🍔 Built With 67 | I built this app with the following technologies: 68 | - HTML 69 | - CSS 70 | - (Plain New) JavaScript 71 | 72 | True, No React, Angular, Vue, yet. As it was done as an initial prototype, I may move the app to a framework later. 73 | 74 | # 🏗️ How to Set up `PromiViz` for Development? 75 | - Clone the repository. 76 | - Browse to the project directory. 77 | - Just run the `index.html` file with any server of your choice. You can use `npx serve`, or if you 78 | are using `VS Code`, you can use the `Live Server` extension to run it. 79 | 80 | # 🛡️ License 81 | This project is licensed under the MIT License - see the [`LICENSE`](LICENSE) file for details. 82 | 83 | # 🏃‍♀️ Deploy 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | # 🤝 Contributing to `PromiViz` 94 | Any kind of positive contribution is welcome! Please help us to grow by contributing to the project. 95 | 96 | If you wish to contribute, you can work on any features or create one on your own. After adding your code, please send a Pull Request. 97 | 98 | > Please read [`CONTRIBUTING`](CONTRIBUTING.md) for details on our [`CODE OF CONDUCT`](CODE_OF_CONDUCT.md) and the process for submitting pull requests to us. 99 | 100 | # 🙏 Support 101 | 102 | We all need support and motivation. `PromiViz` is not an exception. Please give this project a ⭐️ to encourage and show that you liked it. Don't forget to leave a star ⭐️ before you move away. 103 | 104 | If you found the app helpful, consider supporting us with a coffee. 105 | 106 | 107 | 108 | 109 | 110 | --- 111 | 112 |

113 | A ⭐️ to PromiViz is to build it 💪 stronger. 114 |

115 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | if ("serviceWorker" in navigator) { 2 | window.addEventListener("load", function() { 3 | navigator.serviceWorker 4 | .register("/serviceWorker.js") 5 | .then(res => console.log("service worker registered")) 6 | .catch(err => console.log("service worker not registered", err)) 7 | }) 8 | } 9 | 10 | // Get the time represented in the 11 | // format of hh:mm:ss(24 hours clock) 12 | const getTimeClock = (showMs) => { 13 | const now = new Date(); 14 | let h = now.getHours(); 15 | let m = now.getMinutes(); 16 | let s = now.getSeconds(); 17 | let ms = now.getMilliseconds(); 18 | m = padWithZero(m); 19 | s = padWithZero(s); 20 | return showMs ? `${h}:${m}:${s}:${ms}` : `${h}:${m}:${s}`; 21 | }; 22 | 23 | // Pad the single digit numbers with zero 24 | const padWithZero = (num) => { 25 | if (num < 10) {num = "0" + num}; 26 | return num; 27 | } 28 | 29 | // Get the delay values for all the colors 30 | let redDelay = document.getElementById("red-delays-id").value; 31 | let greenDelay = document.getElementById("green-delays-id").value;; 32 | let blueDelay = document.getElementById("blue-delays-id").value;; 33 | console.log(`Initial delays: red - ${redDelay}, green - ${greenDelay}, blue - ${blueDelay}`); 34 | 35 | // Get the reject flag for all the colors 36 | let rejectRed = document.getElementById("red-error-id").checked; 37 | let rejectGreen = document.getElementById("green-error-id").checked; 38 | let rejectBlue = document.getElementById("blue-error-id").checked; 39 | console.log(`Initial rejections: red - ${rejectRed}, green - ${rejectGreen}, blue - ${rejectBlue}`); 40 | 41 | // Retain Logs from LS 42 | let retainLogs = window.localStorage.getItem('promiviz-persist-logs') || false; 43 | document.getElementById('persist-logs').checked = (retainLogs === 'true'); 44 | 45 | // Call this function when a delay is set for a color 46 | const selectDelay = () => { 47 | redDelay = document.getElementById("red-delays-id").value; 48 | greenDelay = document.getElementById("green-delays-id").value;; 49 | blueDelay = document.getElementById("blue-delays-id").value;; 50 | console.log(`Delays: red - ${redDelay}, green - ${greenDelay}, blue - ${blueDelay}`); 51 | selectValue(); 52 | } 53 | 54 | // Call this function when a reject flag is set for a color 55 | const rejectColor = () => { 56 | rejectRed = document.getElementById("red-error-id").checked; 57 | rejectGreen = document.getElementById("green-error-id").checked; 58 | rejectBlue = document.getElementById("blue-error-id").checked; 59 | console.log(`Rejections: red - ${rejectRed}, green - ${rejectGreen}, blue - ${rejectBlue}`); 60 | selectValue(); 61 | } 62 | 63 | // Call this method when a Promise API is selected 64 | const selectValue = () => { 65 | clear(); 66 | if (!retainLogs) { 67 | clearLogs(); 68 | } 69 | const apiSelectBox = document.getElementById("apis-list-id"); 70 | const selected = apiSelectBox.value; 71 | console.log(selected); 72 | switch (selected) { 73 | case 'all': 74 | explain( 75 | `Promise.all takes an array of promises and returns a new promise. 76 | The new promise resolves when all input promises are resolved. In the 77 | example below, notice the time when all promises resolve. It will be 78 | almost equal to the max time taken by a promise(color).` 79 | ); 80 | handleAll(); 81 | break; 82 | case 'any': 83 | explain( 84 | `Promise.any takes an array of promises and returns a new promise. 85 | It resolves when any of the input promises is fulfilled. In the example below, 86 | notice any of the promises resolves when you apply the same delay.` 87 | ); 88 | handleAny(); 89 | break; 90 | case 'race': 91 | explain( 92 | `Promise.race takes an array of promises and returns a new promise. 93 | It resolves when the first promise settles(result/error). In the example below, 94 | notice the promise with the least delay resolves first and in turn, the race is over.` 95 | ); 96 | handleRace(); 97 | break; 98 | case 'allSettled': 99 | explain( 100 | `Promise.allSettled takes an array of promises and returns a new promise. 101 | It resolves when all promises are settled(result/error). In the 102 | example below, notice the time when all promises settle. It will be 103 | almost equal to the max time taken by a promise(color).` 104 | ); 105 | handleAllSettled(); 106 | break; 107 | case 'handleResolve': 108 | explain( 109 | `Promise.resolve creates a resolved promise. In the example below, we resolve 110 | the promises one by one!` 111 | ); 112 | handleResolve(); 113 | break 114 | default: 115 | explain(``); 116 | break; 117 | } 118 | }; 119 | 120 | // Set the value, color, and animation when a Promise Resolves 121 | const setValues = (color, value, duration) => { 122 | document.getElementById(`${color}-id`).innerHTML = value; 123 | document.getElementById(`${color}-id`).parentElement.setAttribute('class', value); 124 | document.getElementById(`${color}-id`).style.animationName = value; 125 | document.getElementById(`${color}-id`).style.animationDuration = duration; 126 | } 127 | 128 | // Clear all the value, color, animations 129 | const clear = () => { 130 | const colors = ['red', 'green', 'blue']; 131 | colors.forEach(color => { 132 | setValues(color, '', '0s'); 133 | }); 134 | } 135 | 136 | // Clear all the logs from the log board 137 | const clearLogs = () => { 138 | const logElem = document.getElementById('log-id'); 139 | logElem.innerHTML = ''; 140 | } 141 | 142 | const persistLogs = () => { 143 | const cb = document.getElementById('persist-logs'); 144 | if(cb.checked) { 145 | retainLogs = true; 146 | } else { 147 | retainLogs = false; 148 | } 149 | window.localStorage.setItem('promiviz-persist-logs', retainLogs) 150 | console.log(`Persistence: ${retainLogs}`); 151 | } 152 | 153 | // Add logs to the log board 154 | const log = (msg, isError) => { 155 | const logElem = document.getElementById('log-id'); 156 | const logListElem = document.createElement('li'); 157 | isError ? logListElem.setAttribute('class', 'error') : logListElem.removeAttribute('class'); 158 | logListElem.innerHTML = `${getTimeClock()} - ${msg}`; 159 | logElem.appendChild(logListElem); 160 | } 161 | 162 | const setTheme = (theme) => { 163 | const logElem = document.getElementById('log-container'); 164 | const itemToRemove = logElem.classList.item(1); 165 | logElem.classList.remove(itemToRemove); 166 | logElem.classList.add(theme); 167 | 168 | const body = document.body; 169 | body.classList.remove(itemToRemove); 170 | body.classList.add(theme); 171 | 172 | const config = document.getElementsByClassName("config"); 173 | config[0].classList.remove(itemToRemove); 174 | config[0].classList.add(theme); 175 | } 176 | 177 | // toggle side nav 178 | const toggleNav = () => { 179 | const navElem = document.getElementById("sidenav-id"); 180 | if (navElem.classList.contains('active')) { 181 | navElem.classList.remove('active'); 182 | } else { 183 | navElem.classList.add('active'); 184 | } 185 | } 186 | 187 | // close the nav bar 188 | const closeNav = () => { 189 | const navElem = document.getElementById("sidenav-id"); 190 | navElem.classList.remove('active'); 191 | } 192 | 193 | const explain = msg => { 194 | const explainElem = document.getElementById("explanation-id"); 195 | explainElem.innerHTML = msg; 196 | } 197 | 198 | // Handle the Promise.all() API 199 | const handleAll = async () => { 200 | try { 201 | log(`🕛 Started handling all the colors using Promise.all([red, green, blue])`); 202 | 203 | const red = new Promise((resolve, reject) => { 204 | setTimeout(() => { 205 | rejectRed ? reject('red') : resolve('red'); 206 | }, redDelay); 207 | }); 208 | const green = new Promise((resolve, reject) => { 209 | setTimeout(() => { 210 | rejectGreen ? reject('green') : resolve('green'); 211 | }, greenDelay); 212 | }); 213 | const blue = new Promise((resolve, reject) => { 214 | setTimeout(() => { 215 | rejectBlue ? reject('blue') : resolve('blue'); 216 | }, blueDelay); 217 | }); 218 | 219 | const colors = await Promise.all([red, green, blue]); 220 | console.log(colors); 221 | colors.forEach(color => { 222 | setValues(color, color, '3s'); 223 | }) 224 | log(`✔️ Finished handling all the colors using Promise.all([red, green, blue])`); 225 | }catch(err) { 226 | log(`❌ Rejected the color ${err}. Rejecting All.`, true); 227 | }; 228 | }; 229 | 230 | // Handle the Promise.any() API 231 | const handleAny = async () => { 232 | try { 233 | log(`🕛 Started handling any of the colors using Promise.any([red, green, blue])`); 234 | 235 | const green = new Promise((resolve, reject) => { 236 | setTimeout(() => { 237 | rejectGreen ? reject('green') : resolve('green'); 238 | }, greenDelay); 239 | }); 240 | 241 | const red = new Promise((resolve, reject) => { 242 | setTimeout(() => { 243 | rejectRed ? reject('red') : resolve('red'); 244 | }, redDelay); 245 | }); 246 | const blue = new Promise((resolve, reject) => { 247 | setTimeout(() => { 248 | rejectBlue ? reject('blue') : resolve('blue'); 249 | }, blueDelay); 250 | }); 251 | 252 | const color = await Promise.any([red, green, blue]); 253 | log(`${color} got picked up! Lucky one.`); 254 | setValues(color, color, '3s'); 255 | log(`✔️Finished handling any of the colors using Promise.any([red, green, blue])`); 256 | }catch(err) { 257 | log(`❌ Rejected the color ${err}.`, true); 258 | }; 259 | }; 260 | 261 | // Handle the Promise.race() API 262 | const handleRace = async () => { 263 | try{ 264 | log(`🕛 Started racing of the colors using Promise.race([red, green, blue])`); 265 | 266 | const blue = new Promise((resolve, reject) => { 267 | setTimeout(() => { 268 | rejectBlue ? reject('blue') : resolve('blue'); 269 | }, blueDelay); 270 | }); 271 | const red = new Promise((resolve, reject) => { 272 | setTimeout(() => { 273 | rejectRed ? reject('red') : resolve('red'); 274 | }, redDelay); 275 | }); 276 | const green = new Promise((resolve, reject) => { 277 | setTimeout(() => { 278 | rejectGreen ? reject('green') : resolve('green'); 279 | }, greenDelay); 280 | }); 281 | 282 | const color = await Promise.race([ green, red, blue]); 283 | log(`${color} own the race! Great champ.`); 284 | setValues(color, color, '3s'); 285 | log(`✔️ Finished racing of the colors using Promise.race([red, green, blue])`); 286 | 287 | } catch(err) { 288 | log(`❌ Rejected the color ${err}. Rejecting All`, true); 289 | } 290 | }; 291 | 292 | // Handle the Promise.allSettled() API 293 | const handleAllSettled = async () => { 294 | log(`🕛 Started settling of the colors using Promise.allSettled([red, green, blue])`); 295 | 296 | const red = new Promise((resolve, reject) => { 297 | setTimeout(() => { 298 | rejectRed ? reject('red') : resolve('red'); 299 | }, redDelay); 300 | }); 301 | 302 | const green = new Promise((resolve, reject) => { 303 | setTimeout(() => { 304 | rejectGreen ? reject('green') : resolve('green'); 305 | }, greenDelay); 306 | }); 307 | 308 | const blue = new Promise((resolve, reject) => { 309 | setTimeout(() => { 310 | rejectBlue ? reject('blue') : resolve('blue'); 311 | }, blueDelay); 312 | }); 313 | 314 | const colors = await Promise.allSettled([red, green, blue]); 315 | 316 | console.log(colors); 317 | 318 | for (const {status, value, reason} of colors) { 319 | if (status === 'rejected') { 320 | log(`❌ Rejected the color ${reason}.`, true); 321 | } else if (status === 'fulfilled') { 322 | setValues(value, value, '3s'); 323 | } 324 | } 325 | 326 | log(`✔️ Finished settling of the colors using Promise.allSettled([red, green, blue])`); 327 | }; 328 | 329 | // Handle the Promise.resolve() API 330 | const handleResolve = async () => { 331 | try { 332 | log(`🕛 Resolving all colors individually with Promise.resolve(color => red, green, blue)`); 333 | const red = new Promise((resolve, reject) => { 334 | setTimeout(() => { 335 | rejectRed ? reject('red') : resolve('red'); 336 | }, redDelay); 337 | }); 338 | 339 | const green = new Promise((resolve, reject) => { 340 | setTimeout(() => { 341 | rejectGreen ? reject('green') : resolve('green'); 342 | }, greenDelay); 343 | }); 344 | 345 | const blue = new Promise((resolve, reject) => { 346 | setTimeout(() => { 347 | rejectBlue ? reject('blue') : resolve('blue'); 348 | }, blueDelay); 349 | }); 350 | 351 | const redResolved = await Promise.resolve(red); 352 | log(`✔️ Finished resolving ${redResolved} using Promise.resolve(${redResolved})`); 353 | setValues(redResolved, redResolved, '3s'); 354 | 355 | const greenResolved = await Promise.resolve(green); 356 | log(`✔️ Finished resolving ${greenResolved} using Promise.resolve(${greenResolved})`); 357 | setValues(greenResolved, greenResolved, '3s'); 358 | 359 | const blueResolved = await Promise.resolve(blue); 360 | log(`✔️ Finished resolving ${blueResolved} using Promise.resolve(${blueResolved})`); 361 | setValues(blueResolved, blueResolved, '3s'); 362 | }catch(err) { 363 | log(`❌ Rejected the color ${err}.`, true); 364 | }; 365 | }; 366 | -------------------------------------------------------------------------------- /images/blog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/blog.png -------------------------------------------------------------------------------- /images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/github.png -------------------------------------------------------------------------------- /images/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /images/icons/android-chrome-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/android-chrome-384x384.png -------------------------------------------------------------------------------- /images/icons/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /images/icons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /images/icons/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /images/icons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /images/icons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /images/icons/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /images/icons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /images/icons/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /images/icons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /images/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /images/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/favicon-16x16.png -------------------------------------------------------------------------------- /images/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/favicon-32x32.png -------------------------------------------------------------------------------- /images/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/favicon.ico -------------------------------------------------------------------------------- /images/icons/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/mstile-144x144.png -------------------------------------------------------------------------------- /images/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/mstile-150x150.png -------------------------------------------------------------------------------- /images/icons/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/icons/mstile-70x70.png -------------------------------------------------------------------------------- /images/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/twitter.png -------------------------------------------------------------------------------- /images/youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/images/youtube.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | PromiViz - Visualize Promise APIs 48 | 49 | 50 |
51 |
52 |

🤝 PromiViz

53 |
54 | 55 |
56 |
57 | 58 |
59 | × 60 | Clear Logs 61 | 62 | Persist Logs 63 | 64 | 65 |
66 | Set a Theme 67 | 68 |
  • 69 |
  • 70 |
  • 71 |
  • 72 |
  • 73 |
    74 |
    75 |
    76 | 118 |
    119 |
    120 |
    121 |
    122 | 123 | 124 | 132 |
    133 |
    134 | 135 |
    136 | 137 |
    138 | 139 |
    140 |
    141 |

    142 | 143 | 155 | | 156 | 160 |

    161 | 162 |
    163 |
    164 |

    165 | 166 | 178 | | 179 | 183 |

    184 | 185 |
    186 |
    187 |

    188 | 189 | 201 | | 202 | 206 |

    207 | 208 |
    209 |
    210 | 211 |
    212 |
    213 |

    Logs

    214 |
    215 |
      216 |
      217 | 226 |
      227 |
      228 | 229 | 230 | 231 | -------------------------------------------------------------------------------- /main.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@100;200;300;400;500;600;700;800&display=swap"); 2 | body, html { 3 | padding: 0; 4 | margin: 0; 5 | font-size: 16px; 6 | transition: 0.5s; 7 | font-family: "Poppins", sans-serif; 8 | scroll-behavior: smooth; 9 | height: 100vh; 10 | } 11 | 12 | /* changes */ 13 | body.blue { 14 | background-color: #0093e9; 15 | background-image: linear-gradient(160deg, #0093e9 0%, #80d0c7 100%); 16 | background-size: 100% 820px; 17 | } 18 | 19 | body.red { 20 | background-color: #FFE53B; 21 | background-image: linear-gradient(147deg, #FFE53B 0%, #FF2525 74%); 22 | background-size: 100% 820px; 23 | } 24 | 25 | body.purple { 26 | background-color: #4158D0; 27 | background-image: linear-gradient(43deg, #4158D0 0%, #C850C0 46%, #FFCC70 100%); 28 | background-size: 100% 820px; 29 | } 30 | 31 | body.green { 32 | background-color: #F4D03F; 33 | background-image: linear-gradient(132deg, #F4D03F 0%, #16A085 100%); 34 | background-size: 100% 820px; 35 | } 36 | 37 | body.black { 38 | background-color: #000000; 39 | background-image: linear-gradient(62deg, #615a5a 0%, #a28db6 100%); 40 | background-size: 100% 820px; 41 | } 42 | 43 | /* changes */ 44 | select { 45 | height: 25px; 46 | border-radius: 4px; 47 | border-radius: 40px; 48 | border: 2px solid white; 49 | background-color: transparent; 50 | font-weight: bold; 51 | text-align: center; 52 | padding: 0px 15px 0px 15px; 53 | } 54 | 55 | a:visited{ 56 | color: #ebebeb; 57 | } 58 | 59 | header { 60 | position: sticky; 61 | top: 0; 62 | margin: 0; 63 | background-color: #000; 64 | color: #FFF; 65 | padding: 0.5rem 1rem; 66 | display: flex; 67 | justify-content: space-between; 68 | } 69 | 70 | header h1 { 71 | display: flex; 72 | align-items: center; 73 | margin: 0; 74 | padding: 0; 75 | } 76 | 77 | .content { 78 | display: flex; 79 | flex-direction: column; 80 | align-items: center; 81 | margin: 1rem 5rem 0 5rem; 82 | } 83 | 84 | .config { 85 | padding: 10px; 86 | display: flex; 87 | flex-direction: column; 88 | align-items: center; 89 | width: auto; 90 | font-size: 20px; 91 | font-weight: 500; 92 | margin: 0.5rem; 93 | border-radius: 10px; 94 | } 95 | 96 | .red { 97 | background-color: #f43f3f; 98 | color: #fff; 99 | } 100 | .green { 101 | background-color: #4fff4f; 102 | color: #000; 103 | } 104 | 105 | .blue { 106 | background-color: #8EC5FC; 107 | color: #000; 108 | } 109 | 110 | .black { 111 | color: #FFF; 112 | } 113 | 114 | .config.blue{ 115 | background-color: #80D0C7; 116 | } 117 | 118 | .config.red{ 119 | background-color: #FF2525; 120 | } 121 | 122 | .config.purple{ 123 | background-color: #FFCC70; 124 | } 125 | 126 | .config.green{ 127 | background-color: #16A085; 128 | } 129 | 130 | .config.black{ 131 | background-color: #a28db6; 132 | } 133 | 134 | 135 | .colors { 136 | width: 100%; 137 | display: flex; 138 | justify-content: space-around; 139 | align-items: center; 140 | } 141 | .colors .actions { 142 | font-size: 20px; 143 | } 144 | 145 | .colors div { 146 | margin: 10px; 147 | border: 1px solid #ebebeb; 148 | border-radius: 5px; 149 | width: 100%; 150 | text-align: center; 151 | } 152 | 153 | .colors .color-text { 154 | font-size: 35px; 155 | font-weight: 900; 156 | font-family: monospace; 157 | text-transform: uppercase; 158 | } 159 | 160 | @keyframes red { 161 | from {background-color: #f7f6f6; } 162 | to {background-color: #f43f3f; } 163 | } 164 | 165 | @keyframes green { 166 | from {background-color: #f7f6f6; color: black;} 167 | to {background-color: #4fff4f; color: black;} 168 | } 169 | 170 | @keyframes blue { 171 | from {background-color: #f7f6f6; color: black;} 172 | to {background-color: #5c5ce6; color: white;} 173 | } 174 | 175 | .log-header { 176 | display: flex; 177 | justify-content: space-between; 178 | } 179 | 180 | .logs { 181 | padding: 10px; 182 | margin: 15px; 183 | border-radius: 5px; 184 | background-color: black; 185 | color: white; 186 | font: 1.3rem Inconsolata, monospace; 187 | text-shadow: 0 0 5px #C8C8C8; 188 | width: 100%; 189 | border: 10px solid orange; 190 | } 191 | 192 | .logs.green { 193 | background-image: radial-gradient( 194 | rgba(0, 150, 0, 0.75), black 120% 195 | ); 196 | } 197 | 198 | .logs.purple { 199 | background-image: radial-gradient( 200 | rgb(150 0 117 / 75%), black 120% 201 | ) 202 | } 203 | 204 | .logs.red { 205 | background-image: radial-gradient( #f00, black 120% ); 206 | } 207 | 208 | .logs.blue { 209 | background-image: radial-gradient( 210 | #00c2ff, black 120% 211 | ) 212 | } 213 | 214 | .logs.black { 215 | background-image: radial-gradient( 216 | #000, black 120% 217 | ) 218 | } 219 | 220 | .log-settings { 221 | display: flex; 222 | flex-direction: column; 223 | align-items: flex-start; 224 | } 225 | 226 | .log-settings .log-theme { 227 | display: flex; 228 | list-style: none; 229 | padding-left: 2rem; 230 | } 231 | 232 | .log-settings .log-theme LI { 233 | width: 10px; 234 | height: 10px; 235 | padding: 5px; 236 | margin: 5px; 237 | border-radius: 9px; 238 | cursor: pointer; 239 | } 240 | 241 | .log-settings LI.black { 242 | background-color: #444242; 243 | } 244 | .log-settings LI.purple { 245 | background-color: #bd24bd; 246 | } 247 | .log-settings LI.blue { 248 | background-color: #6464ee; 249 | } 250 | .log-settings LI.green { 251 | background-color: #13b313; 252 | } 253 | 254 | .log-settings LI.red { 255 | background-color: #f94747; 256 | } 257 | 258 | ::selection { 259 | background: #ff6600; 260 | text-shadow: none; 261 | } 262 | 263 | .logs H2 { 264 | margin: 0; 265 | padding: 0; 266 | display: inline; 267 | } 268 | 269 | .logs UL#log-id { 270 | height: 335px; 271 | overflow-y: auto; 272 | } 273 | 274 | .logs UL#log-id LI { 275 | list-style: none; 276 | padding: 0.2rem; 277 | } 278 | 279 | .logs UL#log-id LI.error { 280 | color: red; 281 | } 282 | 283 | .logs .close { 284 | cursor: pointer; 285 | } 286 | 287 | .explanation { 288 | font-size: 18px; 289 | width: 650px; 290 | padding: 0.5rem; 291 | } 292 | 293 | @media screen and (max-width: 660px) { 294 | .content { 295 | margin: 1.5rem 296 | } 297 | 298 | .config { 299 | width: 100%; 300 | } 301 | 302 | .colors { 303 | width: 100%; 304 | display: block; 305 | } 306 | 307 | .colors div { 308 | width: auto; 309 | } 310 | 311 | .explanation { 312 | width: 300px; 313 | } 314 | } 315 | 316 | @media screen and (min-width: 1800px) { 317 | .logs UL#log-id { 318 | height: 560px; 319 | } 320 | } 321 | 322 | footer { 323 | margin: 0 auto; 324 | padding: 0.5rem; 325 | font-size: 1rem; 326 | } 327 | 328 | .sidenav { 329 | width: 0; 330 | position: fixed; 331 | z-index: 1; 332 | top: 57px; 333 | right: 0; 334 | background-color: #111; 335 | overflow-x: hidden; 336 | transition: 0.5s; 337 | padding-top: 10px; 338 | } 339 | 340 | .sidenav a.item { 341 | padding: 8px 8px 8px 32px; 342 | text-decoration: none; 343 | font-size: 20px; 344 | color: #818181; 345 | display: flex; 346 | transition: 0.3s; 347 | } 348 | 349 | .sidenav a.item input { 350 | margin-top: 8px; 351 | } 352 | 353 | .sidenav a:hover { 354 | color: #f1f1f1; 355 | } 356 | 357 | .sidenav .closebtn { 358 | position: absolute; 359 | top: 0; 360 | right: 25px; 361 | font-size: 36px; 362 | margin-left: 50px; 363 | text-decoration: none; 364 | color: #818181; 365 | } 366 | 367 | .sidenav.active { 368 | width: 250px; 369 | } 370 | 371 | @media screen and (max-height: 450px) { 372 | .sidenav {padding-top: 15px;} 373 | .sidenav a {font-size: 18px;} 374 | } 375 | 376 | .social { 377 | display: flex; 378 | justify-content: space-evenly; 379 | margin-bottom: 0.4rem; 380 | } 381 | 382 | .social a:hover { 383 | transform: scale(1.1); 384 | transition: transform 0.1s ease-in; 385 | } 386 | 387 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "name": "PromiViz", 4 | "description": "Visualize the JavaScript Promise APIs and learn. It is a playground to learn about promises faster, ever!", 5 | "short_name": "PromiViz", 6 | "start_url": "index.html", 7 | "display": "standalone", 8 | "background_color": "#fdfdfd", 9 | "theme_color": "#ffffff", 10 | "orientation": "portrait-primary", 11 | "icons": [ 12 | { 13 | "src": "/images/icons/apple-touch-icon-72x72.png", 14 | "type": "image/png", "sizes": "72x72" 15 | }, 16 | { 17 | "src": "/images/icons/apple-touch-icon-144x144.png", 18 | "type": "image/png", "sizes": "144x144" 19 | }, 20 | { 21 | "src": "/images/icons/apple-touch-icon-152x152.png", 22 | "type": "image/png", "sizes": "152x152" 23 | }, 24 | { 25 | "src": "./images/icons/android-chrome-192x192.png", 26 | "type": "image/png", "sizes": "192x192" 27 | }, 28 | { 29 | "src": "./images/icons/android-chrome-384x384.png", 30 | "type": "image/png", "sizes": "384x384" 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /serviceWorker.js: -------------------------------------------------------------------------------- 1 | const staticPromiViz = "promiviz" 2 | 3 | const expectedCaches = [staticPromiViz]; 4 | 5 | const assets = [ 6 | "/", 7 | "/index.html", 8 | "/main.css", 9 | "/app.js", 10 | "/images/blog.png", 11 | "/images/github.png", 12 | "/images/twitter.png", 13 | "/social/landing.png" 14 | ] 15 | 16 | self.addEventListener("install", installEvent => { 17 | installEvent.waitUntil( 18 | caches.open(staticPromiViz).then(cache => { 19 | cache.addAll(assets) 20 | }) 21 | ) 22 | }); 23 | 24 | self.addEventListener('activate', event => { 25 | // delete any caches that aren't in expectedCaches 26 | // which will get rid of promiviz 27 | event.waitUntil( 28 | caches.keys().then(keys => Promise.all( 29 | keys.map(key => { 30 | if (!expectedCaches.includes(key)) { 31 | return caches.delete(key); 32 | } 33 | }) 34 | )).then(() => { 35 | console.log('promiviz now ready to handle fetches!'); 36 | }) 37 | ); 38 | }); 39 | 40 | self.addEventListener("fetch", fetchEvent => { 41 | fetchEvent.respondWith( 42 | caches.match(fetchEvent.request).then(res => { 43 | return res || fetch(fetchEvent.request) 44 | }) 45 | ) 46 | }); -------------------------------------------------------------------------------- /social/landing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/social/landing.png -------------------------------------------------------------------------------- /social/landing2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/promiviz/26f7d676a99896d9517d1fe83ade451269007ef0/social/landing2.png --------------------------------------------------------------------------------