Skip to content
Merged
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ _docs/api/build/
.parcel-cache
node_modules
freesound/static/bw-frontend/dist/
freesound/static/bw-frontend/dist-dark/
bw_static/
npm-debug.log
21 changes: 9 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,23 +81,15 @@ If you a prompted for a password, use `localfreesoundpgpassword`, this is define

docker compose run --rm web python manage.py createsuperuser

11. Build static files (use this every time you edit a frontend file, or use the frontend profile: see next step)

docker compose run --rm frontend_builder npm run build

12. Run services 🎉
11. Run services 🎉

docker compose up

When running this command, the most important services that make Freesound work will be run locally.
This includes the web application and database, but also the search engine, cache manager, queue manager and asynchronous workers, including audio processing.
This includes the web application and database, but also the forntend builder (static files), search engine, cache manager, queue manager and asynchronous workers, including audio processing.
You should be able to point your browser to `http://localhost:8000` and see the Freesound website up and running!

If you are working on frontend assets (JS, CSS, SCSS), use the `frontend` profile to automatically rebuild on changes:

docker compose --profile frontend up

13. Build the search index, so you can search for sounds and forum posts
12. Build the search index, so you can search for sounds and forum posts

# Open a new terminal window so the services started in the previous step keep running
docker compose run --rm web python manage.py reindex_search_engine_sounds
Expand All @@ -110,7 +102,7 @@ If you a prompted for a password, use `localfreesoundpgpassword`, this is define

Because the `web` container mounts a named volume for the home folder of the user running the shell plus process, command history should be kept between container runs :)

14. (extra) Load audio descriptors and similarity vectors to the database and reindex the search index. This is necessary to make audio descriptors available thorugh the API and to make similarity search work. Note that for this to work, you need to have properly set the development data folder, and you should see some files inside the `freesound-data/analysis` folders which store the (previously computed) results of Freesound audio analysers.
13. (extra) Load audio descriptors and similarity vectors to the database and reindex the search index. This is necessary to make audio descriptors available thorugh the API and to make similarity search work. Note that for this to work, you need to have properly set the development data folder, and you should see some files inside the `freesound-data/analysis` folders which store the (previously computed) results of Freesound audio analysers.

# First run the following command which will create relevant objects in the DB. Note that this can take some minutes.
docker compose run --rm web python manage.py create_consolidated_sound_analysis_and_sim_vectors --force
Expand All @@ -124,6 +116,11 @@ The steps above will get Freesound running, but to save resources in your local
docker compose --profile analyzers up # To run all basic services + sound analyzers
docker compose --profile all up # To run all services

Among the services defined in `docker-compose.yml`, there is a `frontend_builder` that will watch for file changes in the `freesound/static/src` directory and automatically rebuild static so you don't have to manually do that. Nevertheless, a build of the frontend canbe triggered by running:

docker compose run --rm frontend_builder npm run build



### Running tests

Expand Down
1 change: 0 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ services:
- .:/code
- /code/node_modules
command: npm run dev
profiles: ["frontend"]

# Search server
search:
Expand Down
8 changes: 1 addition & 7 deletions freesound.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,7 @@
{
"label": "Build static",
"type": "shell",
"command": "docker compose run --rm frontend_builder npm run build && docker compose run --rm web python manage.py collectstatic --clear --noinput",
"problemMatcher": []
},
{
"label": "Install static",
"type": "shell",
"command": "docker compose run --rm frontend_builder npm install",
"command": "docker compose run --rm frontend_builder npm run build",
"problemMatcher": []
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { handleGenericModal } from './modal';

const prepareAfterDownloadSoundModals = () => {
const downloadButtonElements = document.getElementsByClassName(
const downloadButtonElements = [...document.getElementsByClassName(
'sound-download-button'
);
)];
downloadButtonElements.forEach(element => {
const showModalUrl = element.dataset.showAfterDownloadModalUrl;
element.addEventListener('click', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { initializeStuffInContainer } from '../utils/initHelper';

const prepareAsyncSections = container => {
const asyncSectionPlaceholders =
container.getElementsByClassName('async-section');
[...container.getElementsByClassName('async-section')];
asyncSectionPlaceholders.forEach(element => {
const contentUrl = element.dataset.asyncSectionContentUrl;
const req = new XMLHttpRequest();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const updateSubcategoriesList = (

const prepareCategoryFormFields = mainContainer => {
const categoryFieldContainers =
mainContainer.getElementsByClassName('bst-category-field');
[...mainContainer.getElementsByClassName('bst-category-field')];
categoryFieldContainers.forEach(container => {
const hiddenField = container.querySelectorAll('input[type=hidden]')[0];
const topButtons = container.querySelectorAll('.top-buttons .btn');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const handleCollapsable = e => {
const makeCollapsableBlocks = container => {
const collapsableToggles =
container.getElementsByClassName('collapsable-toggle');
collapsableToggles.forEach(element => {
[...collapsableToggles].forEach(element => {
if (element.dataset.initialized !== undefined) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion freesound/static/bw-frontend/src/components/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const makeDropdowns = container => {
const dropdownOptions =
dropdownContainer.getElementsByClassName('dropdown-menu')[0];
dropdownOptions.setAttribute('role', 'menu');
dropdownOptions.getElementsByClassName('dropdown-item').forEach(item => {
[...dropdownOptions.getElementsByClassName('dropdown-item')].forEach(item => {
item.setAttribute('role', 'menuitem');
});
toggle.addEventListener('click', () => toggleExpandDropdown(toggle));
Expand Down
7 changes: 3 additions & 4 deletions freesound/static/bw-frontend/src/components/explicit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ const addExplicitSoundWarnings = container => {
const warningElements = container.getElementsByClassName(
'explicit-sound-blocker'
);
warningElements.forEach(element => {
[...warningElements].forEach(element => {
const dismissButtonAnchor = element.getElementsByTagName('button')[0];
dismissButtonAnchor.addEventListener('click', () => {
element.parentElement
.getElementsByClassName('blur')
.forEach(blurredElement => {
[...element.parentElement
.getElementsByClassName('blur')].forEach(blurredElement => {
blurredElement.classList.remove('blur');
});
element.remove();
Expand Down
2 changes: 1 addition & 1 deletion freesound/static/bw-frontend/src/components/flagging.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function post_flag(div_id, flag_type, object_id, url) {
}

const bindFlagUserButtons = container => {
const flagUserElements = container.getElementsByClassName('post-flag');
const flagUserElements = [...container.getElementsByClassName('post-flag')];
flagUserElements.forEach(element => {
element.addEventListener('click', () => {
post_flag(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const followOrUnFollowTags = (tags, button) => {

const bindFollowTagsButtons = container => {
const followUnfollowButtons =
container.getElementsByClassName('follow-tags-button');
[...container.getElementsByClassName('follow-tags-button')];
followUnfollowButtons.forEach(button => {
const tags = button.dataset.followTagsUrl
.split('/follow/follow_tags/')[1]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
const bindDisableOnSubmitForms = container => {
const formElementsWithDisableOnSubmit =
container.getElementsByClassName('disable-on-submit');
[...container.getElementsByClassName('disable-on-submit')];
formElementsWithDisableOnSubmit.forEach(formElement => {
if (formElement.dataset.alreadyBinded !== undefined) {
return;
}
formElement.dataset.alreadyBinded = true;

formElement.onsubmit = evt => {
var buttonElements = formElement.getElementsByTagName('button');
var buttonElements = [...formElement.getElementsByTagName('button')];
buttonElements.forEach(element => {
element.disabled = true;
if (element.name !== undefined && element == evt.submitter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const formFieldShouldAllowEnterEvents = element => {
};

const bindDoNotSubmitOnEnterForms = container => {
var formElements = container.getElementsByClassName('do-not-submit-on-enter');
var formElements = [...container.getElementsByClassName('do-not-submit-on-enter')];
formElements.forEach(formElement => {
formElement.onkeydown = evt => {
if (evt.key == 'Enter' && !formFieldShouldAllowEnterEvents(evt.target)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ const showGeotagFieldAndRemoveShowButton = (

const prepareGeotagFormFields = container => {
// Note that this need to run after mapbox scripts have been load (for example, after the DOMContentLoaded is fired)
const showGeolocationButtons = container.getElementsByClassName(
const showGeolocationButtons = [...container.getElementsByClassName(
'show-geolocation-button'
);
)];
showGeolocationButtons.forEach(buttonElement => {
const geotagFieldElement = buttonElement.parentNode;
if (geotagFieldElement.dataset.hasGeotag) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const copyValue = () => {
document.addEventListener('DOMContentLoaded', () => {
const showGeotagPickerElements =
document.getElementsByClassName('show-geotag-picker');
showGeotagPickerElements.forEach(element => {
[...showGeotagPickerElements].forEach(element => {
element.setAttribute('onclick', '');
element.addEventListener('click', () => {
showGeotagPickerHelpTool(element.dataset.refElementId);
Expand Down
4 changes: 2 additions & 2 deletions freesound/static/bw-frontend/src/components/mapsMapbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ function toggleMapStyle(map) {
if (map.getStyle().sprite.indexOf(FREESOUND_STREETS_STYLE_ID) !== -1) {
// Using streets map, switch to satellite
map.setStyle('mapbox://styles/freesound/' + FREESOUND_SATELLITE_STYLE_ID);
mapElement.getElementsByClassName('map_terrain_menu').forEach(element => {
[...mapElement.getElementsByClassName('map_terrain_menu')].forEach(element => {
element.innerText = 'Show streets';
});
} else {
// Using satellite map, switch to streets
map.setStyle('mapbox://styles/freesound/' + FREESOUND_STREETS_STYLE_ID);
mapElement.getElementsByClassName('map_terrain_menu').forEach(element => {
[...mapElement.getElementsByClassName('map_terrain_menu')].forEach(element => {
element.innerText = 'Show terrain';
});
}
Expand Down
8 changes: 4 additions & 4 deletions freesound/static/bw-frontend/src/components/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,11 @@ const handleGenericModal = (
});

// Make paginator update modal (if any)
modalContainer
.getElementsByClassName('bw-pagination_container')
[...modalContainer
.getElementsByClassName('bw-pagination_container')]
.forEach(paginationContainer => {
paginationContainer
.getElementsByTagName('a')
[...paginationContainer
.getElementsByTagName('a')]
.forEach(paginatorLinkElement => {
const loadPageUrl = paginatorLinkElement.href;
paginatorLinkElement.href = 'javascript:void(0);';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const togglePackNameDiv = (select, newPackNameDiv) => {
};

const preparePackFormFields = container => {
const packSelectWrappers = container.getElementsByClassName('pack-select');
const packSelectWrappers = [...container.getElementsByClassName('pack-select')];
packSelectWrappers.forEach(selectWrapper => {
// Add event listener to toggle "new pack name" div if "create new pack" is selected
const select = selectWrapper.getElementsByTagName('select')[0];
Expand Down
14 changes: 6 additions & 8 deletions freesound/static/bw-frontend/src/components/player/player-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
} from '../../utils/browser';

const removeAllLastPlayedClasses = () => {
document.getElementsByClassName('last-played').forEach(element => {
[...document.getElementsByClassName('last-played')].forEach(element => {
element.classList.remove('last-played');
});
};
Expand All @@ -40,14 +40,12 @@ const replaceTimesinceIndicators = parentNode => {
// Checks if timesince information has been added in the player metadata and if so, finds if there are
// any elements with class timesince-target and replaces their content with the timesince information
// NOTE: this modifies the sound display UI, not only strictly the "player" UI, but it's here because
// because this seems the best place to handle this logic
// this seems the best place to handle this logic
if (parentNode.dataset.timesince !== undefined) {
parentNode.parentNode
.getElementsByClassName('timesince-target')
.forEach(timesinceTargetElement => {
timesinceTargetElement.innerHTML =
parentNode.dataset.timesince + ' ago';
});
const timesinceTargetElements = parentNode.parentNode.getElementsByClassName('timesince-target');
[...timesinceTargetElements].forEach(timesinceTargetElement => {
timesinceTargetElement.innerHTML = parentNode.dataset.timesince + ' ago';
});
}
};

Expand Down
4 changes: 2 additions & 2 deletions freesound/static/bw-frontend/src/components/player/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const formatAudioDuration = (duration, showMilliseconds) => {
export const stopAllPlayers = () => {
const players = [...document.getElementsByClassName('bw-player')];
players.forEach(player => {
player.getElementsByTagName('audio').forEach(audioElement => {
[...player.getElementsByTagName('audio')].forEach(audioElement => {
audioElement.pause();
});
});
Expand All @@ -54,7 +54,7 @@ export const stopAllPlayers = () => {
export const stopAllPlayersInContainer = container => {
const players = [...container.getElementsByClassName('bw-player')];
players.forEach(player => {
player.getElementsByTagName('audio').forEach(audioElement => {
[...player.getElementsByTagName('audio')].forEach(audioElement => {
audioElement.pause();
});
});
Expand Down
2 changes: 1 addition & 1 deletion freesound/static/bw-frontend/src/components/radio.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const addVisibleRadio = radioEl => {
radioIcon.setAttribute('role', 'radio');
radioIcon.setAttribute('aria-checked', radioEl.checked);
radioEl.addEventListener('change', () => {
const radioOptions = document.getElementsByName(radioEl.name);
const radioOptions = [...document.getElementsByName(radioEl.name)];
radioOptions.forEach(option => {
option.parentNode
.getElementsByClassName('bw-icon-radio-unchecked')[0]
Expand Down
2 changes: 1 addition & 1 deletion freesound/static/bw-frontend/src/components/rating.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ const handleRatingInput = ratingInput => {

const makeRatingWidgets = container => {
const ratingInputs = container.getElementsByClassName('bw-rating__input');
ratingInputs.forEach(ratingInput => {
[...ratingInputs].forEach(ratingInput => {
ratingInput.addEventListener('click', evt => {
handleRatingInput(ratingInput);
evt.stopPropagation();
Expand Down
2 changes: 1 addition & 1 deletion freesound/static/bw-frontend/src/components/scrollSpy.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isScrolledIntoView } from '../utils/elementVisibility';
import debounce from 'lodash.debounce';

const scrollSpyElements = document.getElementsByClassName('scroll-spy');
const scrollSpyElements = [...document.getElementsByClassName('scroll-spy')];

const addClassToSpiedElement = () => {
let elementToActivate = undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ const updateTags = (inputElement, newTagsStr) => {
};

const prepareTagsFormFields = container => {
const tagsInputFields = container.getElementsByClassName('tags-field');
const tagsInputFields = [...container.getElementsByClassName('tags-field')];
tagsInputFields.forEach(tagsFieldElement => {
const tagsHiddenInput = tagsFieldElement.querySelectorAll(
'input[name$="tags"]'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { showToast } from './toast';

const bindUnsecureImageCheckListeners = container => {
const elementsToCheckForUnsecureImages = container.getElementsByClassName(
const elementsToCheckForUnsecureImages = [...container.getElementsByClassName(
'unsecure-image-check'
);
)];
elementsToCheckForUnsecureImages.forEach(element => {
['keydown', 'focusin'].forEach(eventName => {
element.addEventListener(eventName, () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ const saveAnnotation = (addAnnotationUrl, text, user_id) => {
// Annotation saved successfully. Close model and show feedback
dismissModal(`moderationAnnotationsModal`);
const responseData = JSON.parse(responseText);
document
.getElementsByClassName('annotation-counter-' + user_id)
[...document
.getElementsByClassName('annotation-counter-' + user_id)]
.forEach(element => {
element.innerText = responseData.num_annotations;
});
Expand Down
1 change: 1 addition & 0 deletions freesound/static/bw-frontend/src/index-dark.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
import 'normalize.css';
import '../styles/index-dark.scss';
2 changes: 1 addition & 1 deletion freesound/static/bw-frontend/src/pages/donate.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const donationButtonPaypalElement = document.getElementById(
'donation_button_paypal'
);
const recurringCheckboxElement = document.getElementById('id_recurring');
const nameOptionRadioButtons = document.getElementsByName('donation_type');
const nameOptionRadioButtons = [...document.getElementsByName('donation_type')];
const nameOptionOtherInputElement = document.getElementById('id_name_option');

// Make "other" input appear or disappear accordingly
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ var inputTypeSubmitElements = formElement.querySelectorAll(
);
inputTypeSubmitElements.forEach(button => {
button.addEventListener('click', e => {
const tagsInputFields = formElement.getElementsByClassName('tags-field');
const tagsInputFields = [...formElement.getElementsByClassName('tags-field')];
tagsInputFields.forEach(tagsFieldElement => {
const inputElement =
tagsFieldElement.getElementsByClassName('tags-input')[0];
Expand Down
Loading