Skip to content
This repository has been archived by the owner on Apr 25, 2024. It is now read-only.

Commit

Permalink
Merge pull request #901 from creativecommons/nsfw_filter
Browse files Browse the repository at this point in the history
NSFW filter
  • Loading branch information
brenoferreira authored May 4, 2020
2 parents 1d58bdf + af15525 commit cb2cce6
Show file tree
Hide file tree
Showing 18 changed files with 190 additions and 80 deletions.
5 changes: 1 addition & 4 deletions src/components/ContentReport/ContentReportForm.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="card padding-normal is-clearfix report-form">
<div class="padding-normal is-clearfix report-form">
<button class="button close-button is-text tiny is-pulled-right is-block has-text-grey-light"
@click="closeForm()">
<i class="icon cross"></i>
Expand Down Expand Up @@ -132,9 +132,6 @@ export default {
</script>

<style lang="scss" scoped>
.card {
width: 22rem;
}
.reason {
width: 100%;
height: 6rem;
Expand Down
35 changes: 0 additions & 35 deletions src/components/FilterBlock.vue

This file was deleted.

35 changes: 35 additions & 0 deletions src/components/Filters/FilterBlock.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<template>
<button class="filter-block button tiny tag margin-horizontal-smaller"
v-if="filterType === 'searchBy' || filterType === 'mature'"
role="filter"
:aria-label="label">
<span>{{ this.$props.label }}</span>
<span class="close margin-left-small"
tabindex="0"
@click="onClickIsolatedFilter"><i class="icon cross" /></span>
</button>
<button v-else
class="filter-block button tiny tag margin-horizontal-smaller"
role="filter"
:aria-label="label">
<span>{{ this.$props.label }}</span>
<span class="close padding-left-normal"
tabindex="0"
@click="onClick"><i class="icon cross" /></span>
</button>
</template>
<script>
export default {
name: 'filter-block',
props: ['code', 'filterType', 'label'],
methods: {
onClick() {
this.$emit('filterChanged', { code: this.$props.code, filterType: this.$props.filterType });
},
onClickIsolatedFilter() {
this.$emit('filterChanged', { filterType: this.$props.filterType });
},
},
};
</script>

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
title="toggle filters visibility" />
</button>
</div>
<template v-if="filtersVisible">
<template v-if="filtersVisible && options">
<div v-for="(item, index) in options" :key="index" class="margin-top-small">
<label class="checkbox" :for="item.code">
<input type="checkbox"
Expand All @@ -25,12 +25,22 @@
</label>
</div>
</template>
<template v-if="filtersVisible && filterType === 'mature'">
<label class="checkbox margin-top-small" for="mature">
<input id="mature"
class="filter-checkbox"
type="checkbox"
:checked="checked"
@change="onValueChange">
Enable Mature Content
</label>
</template>
</div>
</template>
<script>
export default {
name: 'filter-check-list',
props: ['options', 'title', 'filterType', 'disabled'],
props: ['options', 'title', 'filterType', 'disabled', 'checked'],
data() {
return { filtersVisible: false };
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,65 @@
<template>
<div class="filter-display padding-horizontal-normal" aria-live="polite">
<span v-if="anyFilterApplied()" class="caption has-text-weight-semibold">Filter By</span>
<span v-if="anyFilterApplied" class="caption has-text-weight-semibold">Filter By</span>
<span v-for="filter in getFilters('licenses')" :key="filter.code">
<filter-block :filter="filter"
<filter-block :code="filter.code"
:label="filter.name"
filterType="licenses"
@filterChanged="onUpdateFilter" />
</span>
<span v-for="filter in getFilters('licenseTypes')" :key="filter.code">
<filter-block :filter="filter"
<filter-block :code="filter.code"
:label="filter.name"
filterType="licenseTypes"
@filterChanged="onUpdateFilter" />
</span>
<span v-for="filter in getFilters('categories')" :key="filter.code">
<filter-block :filter="filter"
<filter-block :code="filter.code"
:label="filter.name"
filterType="categories"
@filterChanged="onUpdateFilter" />
</span>
<span v-for="filter in getFilters('extensions')" :key="filter.code">
<filter-block :filter="filter"
<filter-block :code="filter.code"
:label="filter.name"
filterType="extensions"
@filterChanged="onUpdateFilter" />
</span>
<span v-for="filter in getFilters('aspectRatios')" :key="filter.code">
<filter-block :filter="filter"
<filter-block :code="filter.code"
:label="filter.name"
filterType="aspectRatios"
@filterChanged="onUpdateFilter" />
</span>
<span v-for="filter in getFilters('sizes')" :key="filter.code">
<filter-block :filter="filter"
<filter-block :code="filter.code"
:label="filter.name"
filterType="sizes"
@filterChanged="onUpdateFilter" />
</span>
<span v-for="filter in getFilters('providers')" :key="filter.code">
<filter-block :filter="filter"
<filter-block :code="filter.code"
:label="filter.name"
filterType="providers"
@filterChanged="onUpdateFilter" />
</span>
<span>
<filter-block v-if="searchByFilters"
:filter="searchByFilters"
filterType="searchByCreator"
@filterChanged="onUpdateSearchByCreator" />
<filter-block v-if="searchByCreator"
label="Creator"
filterType="searchBy"
@filterChanged="onUpdateBoolFilter" />
</span>
<span>
<filter-block v-if="mature"
label="Mature"
filterType="mature"
@filterChanged="onUpdateBoolFilter" />
</span>
</div>
</template>
<script>
import { TOGGLE_FILTER } from '@/store/action-types';
import FilterBlock from '@/components/FilterBlock';
import FilterBlock from '@/components/Filters/FilterBlock';
const filterMap = {
licenses: 'license',
Expand All @@ -65,8 +78,14 @@ export default {
FilterBlock,
},
computed: {
searchByFilters() {
return this.$store.state.filters.searchBy.creator ? this.$store.state.filters.searchBy : null;
searchByCreator() {
return this.$store.state.filters.searchBy.creator;
},
mature() {
return this.$store.state.filters.mature;
},
anyFilterApplied() {
return this.$store.state.isFilterApplied;
},
},
methods: {
Expand All @@ -80,11 +99,6 @@ export default {
});
return filterTags;
},
anyFilterApplied() {
const filters = Object.keys(filterMap).map(key => this.getFilters(key));
return filters.some(f => f.length !== 0);
},
onUpdateFilter({ code, filterType }) {
this.$store.dispatch(TOGGLE_FILTER, {
code,
Expand All @@ -94,9 +108,9 @@ export default {
shouldNavigate: true,
});
},
onUpdateSearchByCreator() {
onUpdateBoolFilter({ filterType }) {
this.$store.dispatch(TOGGLE_FILTER, {
filterType: 'searchBy',
filterType,
isCollectionsPage: this.$props.isCollectionsPage,
provider: this.$props.provider,
shouldNavigate: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,19 @@
title="Image Size"
filterType="sizes"
@filterChanged="onUpdateFilter" />
<filter-check-list title="Search Settings"
filterType="mature"
:checked="filters.mature"
@filterChanged="onUpdateFilter" />

<div class="margin-normal filter-option small-filter search-filters_search-by">
<input type="checkbox" id="creator-chk"
:checked="filters.searchBy.creator"
@change="onUpdateSearchByCreator">
<label for="creator-chk">Search by Creator</label>
</div>
</form>

<div class="margin-normal filter-option small-filter search-filters_search-by">
<input type="checkbox" id="creator-chk"
:checked="filters.searchBy.creator"
@change="onUpdateSearchByCreator">
<label for="creator-chk">Search by Creator</label>
</div>
<div class="margin-big padding-bottom-normal clear-filters"
v-if="isFilterApplied">
<button class="button tiny"
Expand Down
4 changes: 2 additions & 2 deletions src/pages/client/BrowsePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import FooterSection from '@/components/FooterSection';
import HeaderSection from '@/components/HeaderSection';
import SearchGrid from '@/components/SearchGrid';
import SearchGridForm from '@/components/SearchGridForm';
import SearchGridFilter from '@/components/SearchGridFilter';
import FilterDisplay from '@/components/FilterDisplay';
import SearchGridFilter from '@/components/Filters/SearchGridFilter';
import FilterDisplay from '@/components/Filters/FilterDisplay';
import BrowsePageMixin from '@/pages/mixins/BrowsePageMixin';
const BrowsePage = {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/client/CollectionBrowsePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import FooterSection from '@/components/FooterSection';
import HeaderSection from '@/components/HeaderSection';
import SearchGrid from '@/components/SearchGrid';
import SearchGridForm from '@/components/SearchGridForm';
import SearchGridFilter from '@/components/SearchGridFilter';
import SearchGridFilter from '@/components/Filters/SearchGridFilter';
import CollectionBrowseMixin from '@/pages/mixins/CollectionBrowseMixin';
const CollectionBrowsePage = {
Expand Down
4 changes: 2 additions & 2 deletions src/pages/server/BrowsePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import FooterSection from '@/components/FooterSection';
import HeaderSection from '@/components/HeaderSection';
import SearchGridForm from '@/components/SearchGridForm';
import SearchGridFilter from '@/components/SearchGridFilter';
import SearchGridFilter from '@/components/Filters/SearchGridFilter';
import BrowsePageMixin from '@/pages/mixins/BrowsePageMixin';
import FilterDisplay from '@/components/FilterDisplay';
import FilterDisplay from '@/components/Filters/FilterDisplay';
import ServerPrefetchProvidersMixin from '@/pages/mixins/ServerPrefetchProvidersMixin';
const BrowsePage = {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/server/CollectionBrowsePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import FooterSection from '@/components/FooterSection';
import HeaderSection from '@/components/HeaderSection';
import SearchGridForm from '@/components/SearchGridForm';
import SearchGridFilter from '@/components/SearchGridFilter';
import SearchGridFilter from '@/components/Filters/SearchGridFilter';
import CollectionBrowseMixin from '@/pages/mixins/CollectionBrowseMixin';
const CollectionBrowsePage = {
Expand Down
5 changes: 5 additions & 0 deletions src/store/filter-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,15 @@ export const filterData = {
searchBy: {
creator: false,
},
mature: false,
};

const MIN_SCREEN_WIDTH_FILTER_VISIBLE_BY_DEFAULT = 800;
const hideFiltersIfMobileScreen = () => screenWidth() > MIN_SCREEN_WIDTH_FILTER_VISIBLE_BY_DEFAULT;

const isFilterApplied = filters => Object.keys(filters).some((filterKey) => {
if (filterKey === 'searchBy') { return filters.searchBy.creator; }
else if (filterKey === 'mature') { return filters.mature; }

return filters[filterKey].some(filter => filter.checked);
});
Expand Down Expand Up @@ -95,6 +97,9 @@ function setFilter(state, params, path, redirect) {
if (params.filterType === 'searchBy') {
state.filters.searchBy.creator = !state.filters.searchBy.creator;
}
else if (params.filterType === 'mature') {
state.filters.mature = !state.filters.mature;
}
else {
const filters = state.filters[params.filterType];
filters[params.codeIdx].checked = !filters[params.codeIdx].checked;
Expand Down
1 change: 1 addition & 0 deletions src/styles/photodetails.scss
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
background: #ffffff;
border: 2px solid #D8D8D8;
z-index: 10;
width: 22rem;
}
.report-form:after, .report-form:before {
bottom: 100%;
Expand Down
17 changes: 17 additions & 0 deletions src/utils/searchQueryTransform.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const filtersToQueryData = (filters) => {
}, queryDataObject);

queryDataObject.searchBy = filters.searchBy.creator ? 'creator' : '';
queryDataObject.mature = filters.mature;

return queryDataObject;
};
Expand Down Expand Up @@ -79,9 +80,24 @@ export const queryToFilterData = (queryString) => {
filters.searchBy.creator = true;
}

const mature = getParameterByName('mature', queryString);
if (mature) {
filters.mature = mature.toLowerCase() === 'true';
}

return filters;
};

/**
* converts the url query string to the data format accepted by the API.
*
* this is slightly different from filtersToQueryData as this converts the
* query string and that converts the filter data.
*
* TODO: we might be able to refactor to eliminate the need for these two
* separate functions.
* @param {string} query string
*/
export const queryStringToQueryData = (queryString) => {
const queryDataObject = {};
Object.keys(filterPropertyMappings).forEach((filterDataKey) => {
Expand All @@ -91,6 +107,7 @@ export const queryStringToQueryData = (queryString) => {

queryDataObject.q = getParameterByName('q', queryString);
queryDataObject.searchBy = getParameterByName('searchBy', queryString);
queryDataObject.mature = getParameterByName('mature', queryString);

return queryDataObject;
};
2 changes: 1 addition & 1 deletion test/unit/specs/components/filter-block.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import FilterBlock from '@/components/FilterBlock';
import FilterBlock from '@/components/Filters/FilterBlock';
import render from '../../test-utils/render';

describe('FilterBlock', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/unit/specs/components/filter-checklist.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import FilterChecklist from '@/components/FilterChecklist';
import FilterChecklist from '@/components/Filters/FilterChecklist';
import render from '../../test-utils/render';

describe('FilterChecklist', () => {
Expand Down
Loading

0 comments on commit cb2cce6

Please sign in to comment.