Skip to content

app: refactor indicators and filters to provide more robust system for adding new icons and transitions #29

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

Draft
wants to merge 1 commit into
base: latest
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions layouts/category.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
</div>
{{/if}}
</main>
<script src="indicators.js"></script>
<script src="firebase.js"></script>
</body>
</html>
Expand Down
1 change: 1 addition & 0 deletions layouts/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
{{/each}}
</div>
</main>
<script src="indicators.js"></script>
<script src="firebase.js"></script>
<script src="filter.js"></script>
</body>
Expand Down
6 changes: 2 additions & 4 deletions layouts/skill.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@
<h1 class="display-5 d-flex">
<span class="d-block mt-4">
<span class="indicator indicator-detail text-center p-1" data-slug="{{slug}}">
<span class="done">✅️</span>
<span class="star">⭐️</span>
<span class="maybe">❓</span>
<span class="not-done">❔️</span>
<span class="indicator-icon"></span>
</span>
{{name}}
</span>
Expand Down Expand Up @@ -144,6 +141,7 @@
</div>

</main>
<script src="indicators.js"></script>
<script src="firebase.js"></script>
<script>
function htmlDecode(input) {
Expand Down
16 changes: 7 additions & 9 deletions partials/header.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@
<div class="filter-group ms-5">
<span class="text-white me-2">filters</span>
<div class="btn-group bg-dark" role="group">
<button type="button" class="btn px-4 btn-outline-light active filter-not-done-or-maybe">❔️</button>
<button type="button" class="btn px-4 btn-outline-light active filter-star">⭐️</button>
<button type="button" class="btn px-4 btn-outline-light active filter-done">✅️</button>
<button type="button" class="btn px-4 btn-outline-light active filter-indicator"></button>
</div>
<div class="btn-group bg-dark ms-3" role="group">
<button type="button" class="btn px-3 btn-outline-light active filter-level-1">1</button>
<button type="button" class="btn px-3 btn-outline-light active filter-level-2">2</button>
<button type="button" class="btn px-3 btn-outline-light active filter-level-3">3</button>
<button type="button" class="btn px-3 btn-outline-light active filter-level-4">4</button>
<button type="button" class="btn px-3 btn-outline-light active filter-level-5">5</button>
<button type="button" class="btn px-3 btn-outline-light active filter-extra">extra</button>
<button type="button" class="btn px-3 btn-outline-light active filter-level" data-level="1">1</button>
<button type="button" class="btn px-3 btn-outline-light active filter-level" data-level="2">2</button>
<button type="button" class="btn px-3 btn-outline-light active filter-level" data-level="3">3</button>
<button type="button" class="btn px-3 btn-outline-light active filter-level" data-level="4">4</button>
<button type="button" class="btn px-3 btn-outline-light active filter-level" data-level="5">5</button>
<button type="button" class="btn px-3 btn-outline-light active filter-level" data-level="extra">extra</button>
</div>
</div>
<span class="filter-nothing-found alert alert-danger mt-4 d-none" role="alert">Nothing has been found.</span>
Expand Down
17 changes: 3 additions & 14 deletions partials/list-item.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,12 @@
>
{{#if skill}}
<span
class="
indicator indicator-list text-center p-1
{{#ifEquals level 0 }}is-level-0{{/ifEquals}}
{{#ifEquals level 1 }}is-level-1{{/ifEquals}}
{{#ifEquals level 2 }}is-level-2{{/ifEquals}}
{{#ifEquals level 3 }}is-level-3{{/ifEquals}}
{{#ifEquals level 4 }}is-level-4{{/ifEquals}}
{{#ifEquals level 5 }}is-level-5{{/ifEquals}}
{{#ifEquals level "extra" }}is-extra{{/ifEquals}}
"
class="indicator indicator-list text-center p-1"
data-slug="{{slug}}"
data-level="{{level}}"
>
<span class="locked">🔒️</span>
<span class="done">✅️</span>
<span class="star">⭐️</span>
<span class="maybe">❓</span>
<span class="not-done">❔️</span>
<span class="indicator-icon"></span>
</span>
{{#unless resources}}
{{#unless text}}
Expand Down
111 changes: 48 additions & 63 deletions src/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,7 @@ const allGroups = document.querySelectorAll(".skill-group");
const allColumns = document.querySelectorAll(".skill-section");
const nothingFound = document.querySelector(".filter-nothing-found");

const doneFilter = document.querySelector(".filter-done");
const starFilter = document.querySelector(".filter-star");
const notDoneOrMaybeFilter = document.querySelector(".filter-not-done-or-maybe");
const extraFilter = document.querySelector(".filter-extra");

const levelFilter1 = document.querySelector(".filter-level-1");
const levelFilter2 = document.querySelector(".filter-level-2");
const levelFilter3 = document.querySelector(".filter-level-3");
const levelFilter4 = document.querySelector(".filter-level-4");
const levelFilter5 = document.querySelector(".filter-level-5");
const levelFilters = document.querySelectorAll(".filter-level");

const filterCounter = document.querySelector(".filter-counter");
const shownSkills = document.querySelector(".shown-skills");
Expand All @@ -21,47 +12,53 @@ const allItemsCount = allItems.length

document.querySelector(".total-skills").innerHTML = allItemsCount;

const filterPlaceholder = document.querySelector(".filter-indicator");
const filterContainer = filterPlaceholder.parentElement;
filterPlaceholder.remove();

const indicatorFilters = Object.keys(INDICATOR_BIG_FILTERS).map(icon => {
let filterButton = filterPlaceholder.cloneNode(true);
filterButton.textContent = icon;
filterButton.dataset.icon = icon;
filterContainer.appendChild(filterButton);
return filterButton;
});

const FILTERS_VALUE = "FILTERS_VALUE";

function getFiltersValues() {
let levelFiltersValues = {};
levelFilters.forEach(el => {
levelFiltersValues[el.dataset.level] = el.classList.contains("active");
});

let indicatorFiltersValues = {};
indicatorFilters.forEach(el => {
INDICATOR_BIG_FILTERS[el.dataset.icon].forEach(indicator => {
indicatorFiltersValues[indicator] = el.classList.contains("active");
});
});

return {levelFiltersValues, indicatorFiltersValues};
}

function filterItems() {
let filtersValue = {
done: doneFilter.classList.contains("active"),
star: starFilter.classList.contains("active"),
notDoneOrMaybe: notDoneOrMaybeFilter.classList.contains("active"),
extra: extraFilter.classList.contains("active"),
level1: levelFilter1.classList.contains("active"),
level2: levelFilter2.classList.contains("active"),
level3: levelFilter3.classList.contains("active"),
level4: levelFilter4.classList.contains("active"),
level5: levelFilter5.classList.contains("active"),
};
let {levelFiltersValues, indicatorFiltersValues} = getFiltersValues();
levelFiltersValues[0] = levelFiltersValues[1];

allItems.forEach(el => {
let indicator = el.querySelector(".indicator");
let type = indicator.classList.contains("is-done") ? "done"
: indicator.classList.contains("is-star") ? "star"
: "notDoneOrMaybe";
let isExtra = indicator.classList.contains("is-extra");
let isLevel1 = indicator.classList.contains("is-level-1");
let isLevel2 = indicator.classList.contains("is-level-2");
let isLevel3 = indicator.classList.contains("is-level-3");
let isLevel4 = indicator.classList.contains("is-level-4");
let isLevel5 = indicator.classList.contains("is-level-5");

let isActive =
(isLevel1 && !filtersValue.level1) ||
(isLevel2 && !filtersValue.level2) ||
(isLevel3 && !filtersValue.level3) ||
(isLevel4 && !filtersValue.level4) ||
(isLevel5 && !filtersValue.level5) ||
(isExtra && !filtersValue.extra) ? false : filtersValue[type];

let isActiveByLevel = levelFiltersValues[indicator.dataset.level];
let isActiveByIndicator = indicatorFiltersValues[indicator.dataset.currentIndicator];
let isActive = isActiveByLevel && isActiveByIndicator;

el.classList.toggle("d-flex", isActive);
el.classList.toggle("d-none", !isActive);
});

allGroups.forEach(el => {
let addOrRemove = el.querySelectorAll(".skill-item.d-flex").length === 0 && (filtersValue.done || filtersValue.star || filtersValue.notDoneOrMaybe);
let addOrRemove = el.querySelectorAll(".skill-item.d-flex").length === 0;
el.classList.toggle("d-none", addOrRemove);
el.previousElementSibling.classList.toggle("d-none", addOrRemove);
});
Expand All @@ -71,7 +68,7 @@ function filterItems() {
el.classList.toggle("d-none", addOrRemove);
});

let nothingWasFound = document.querySelectorAll(".skill-item.d-flex").length === 0 && (filtersValue.done || filtersValue.star || filtersValue.notDoneOrMaybe);
let nothingWasFound = document.querySelectorAll(".skill-item.d-flex").length === 0;
nothingFound.classList.toggle("d-none", !nothingWasFound);

let shownSkillsCount = document.querySelectorAll(".skill-item.d-flex").length;
Expand All @@ -93,7 +90,7 @@ function showAllItems() {
allItems.forEach(el => {
el.classList.add("d-flex");
el.classList.remove("d-none");
el.querySelector(".indicator").classList.remove("is-done", "is-star");
el.querySelector(".indicator .indicator-icon").textContent = "";
});

allGroups.forEach(el => {
Expand All @@ -105,17 +102,7 @@ function showAllItems() {
}

function saveFilters() {
let filtersStateToSave = {
done: doneFilter.classList.contains("active"),
star: starFilter.classList.contains("active"),
notDone: notDoneOrMaybeFilter.classList.contains("active"),
extra: extraFilter.classList.contains("active"),
level1: levelFilter1.classList.contains("active"),
level2: levelFilter2.classList.contains("active"),
level3: levelFilter3.classList.contains("active"),
level4: levelFilter4.classList.contains("active"),
level5: levelFilter5.classList.contains("active"),
};
let filtersStateToSave = getFiltersValues();

let filtersKey = FILTERS_VALUE;
if (isAdmin) {
Expand All @@ -140,15 +127,14 @@ function loadFilters() {
if (filtersStateToLoad) {
try {
filtersStateToLoad = JSON.parse(filtersStateToLoad);
doneFilter.classList.toggle("active", filtersStateToLoad.done);
starFilter.classList.toggle("active", filtersStateToLoad.star);
notDoneOrMaybeFilter.classList.toggle("active", filtersStateToLoad.notDone);
extraFilter.classList.toggle("active", filtersStateToLoad.extra);
levelFilter1.classList.toggle("active", filtersStateToLoad.level1);
levelFilter2.classList.toggle("active", filtersStateToLoad.level2);
levelFilter3.classList.toggle("active", filtersStateToLoad.level3);
levelFilter4.classList.toggle("active", filtersStateToLoad.level4);
levelFilter5.classList.toggle("active", filtersStateToLoad.level5);

// @TODO new implementation

// backward compatibility
if ("done" in filtersStateToLoad) {

// @TODO backward compatibility implementation

} catch (e) {
}
}
Expand All @@ -160,8 +146,7 @@ function onFilterButtonClick(e) {
filterItems();
}

[doneFilter, starFilter, notDoneOrMaybeFilter, extraFilter, levelFilter1, levelFilter2, levelFilter3, levelFilter4, levelFilter5]
.forEach(el => el.addEventListener("click", onFilterButtonClick));
[...indicatorFilters, ...levelFilters].forEach(el => el.addEventListener("click", onFilterButtonClick));
loadFilters();
INDICATOR_CHANGE_CALLBACKS.push(filterItems);
USER_LOGGED_OUT_CALLBACKS.push(showAllItems);
Expand Down
17 changes: 2 additions & 15 deletions src/firebase.css
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
.not-done,
.maybe,
.done,
.star,
.indicator.is-done .not-done,
.indicator.is-star .not-done,
.indicator.is-maybe .not-done,
.indicator-icon,
.logged-in .locked,
.indicator.not-done .locked,
.indicator.is-done .locked,
.indicator.is-star .locked,
.indicator.is-maybe .locked,
.logged-in .note.note-empty,
.logged-in .login,
.logout,
Expand All @@ -22,10 +12,7 @@
display: none;
}

.indicator.is-done .done,
.indicator.is-star .star,
.indicator.is-maybe .maybe,
.logged-in .not-done,
.logged-in .indicator-icon,
.logged-in .note,
.logged-in .logout,
.logged-in .filter-group,
Expand Down
43 changes: 17 additions & 26 deletions src/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,38 +39,27 @@ let indicators = document.querySelectorAll(".indicator");

function setStateOfAllIndicators(data) {
indicators.forEach(indicator => {
indicator.classList.toggle("is-done", data[indicator.dataset.slug] === true);
indicator.classList.toggle("is-star", data[indicator.dataset.slug] === 'star');
indicator.classList.toggle("is-maybe", data[indicator.dataset.slug] === 'maybe');
let currentIndicator = convertIndicatorForBackwardCompatibility(data[indicator.dataset.slug]) || DEFAULT_INDICATOR;
indicator.dataset.currentIndicator = currentIndicator;
indicator.querySelector(".indicator-icon").textContent = INDICATOR_ICONS[currentIndicator];
});
}

function indicatorListener(event) {
event.preventDefault();

let isDone = this.classList.contains("is-done");
let isStar = this.classList.contains("is-star");
let isMaybe = this.classList.contains("is-maybe");

let newValue;

if (userFlags.intro) {
// maybe → not-done
// any other → maybe
newValue = isMaybe ? "not-done" : "maybe";
} else if (event.shiftKey) {
// anything → maybe
newValue = "maybe";
} else {
// star → done
// done → not-done
// not-done or maybe → star
newValue = isStar ? "done" : isDone ? "not-done" : "star";
}

// convert original values to boolean to preserve backward compatibility
if (newValue === "done") newValue = true;
if (newValue === "not-done") newValue = false;
let newValue = Object.entries(INDICATOR_TRANSITIONS)
.find(([indicator]) => this.dataset.currentIndicator === indicator)[1]({
userFlags,
shift: event.shiftKey,
ctrl: event.ctrlKey,
alt: event.altKey,
altGr: event.ctrlKey && event.altKey,
meta: event.metaKey,
left: event.button === 0,
middle: event.button === 1,
right: event.button === 2,
});

firebase.firestore().collection("db").doc("v1")
.collection("users").doc(sessionStorage.getItem(SELECTED_USER_ID))
Expand All @@ -80,6 +69,8 @@ function indicatorListener(event) {

indicators.forEach(indicator => {
indicator.addEventListener("click", indicatorListener, false);
indicator.addEventListener("auxclick", indicatorListener, false);
indicator.addEventListener("contextmenu", e => e.preventDefault(), false);
});

let removeFirebaseNoteListener = () => {
Expand Down
Loading