Merged filters into new settings dialog, added experimental summary field.

This commit is contained in:
DebaucheryLibrarian
2022-11-28 03:33:46 +01:00
parent 637669e3d1
commit b5e308562e
15 changed files with 740 additions and 72 deletions

View File

@@ -0,0 +1,83 @@
<template>
<div class="dialog-section">
<h3 class="form-heading">Show me</h3>
<ul class="tags nolist">
<li
v-for="tag in tags"
:key="tag"
class="tags-item"
>
<Checkbox
:checked="!tagFilter.includes(tag)"
:label="tag"
class="tag"
@change="(state) => filterTag(tag, state)"
/>
</li>
</ul>
<p class="disclaimer">You may still incidentally see filtered out content</p>
</div>
</template>
<script>
import Checkbox from '../form/checkbox.vue';
function tagFilter() {
return this.$store.state.ui.tagFilter;
}
function filterTag(tag, isChecked) {
if (isChecked) {
this.$store.dispatch('setTagFilter', this.tagFilter.filter((filteredTag) => filteredTag !== tag));
} else {
this.$store.dispatch('setTagFilter', this.tagFilter.concat(tag));
}
}
export default {
components: {
Checkbox,
},
data() {
return {
tags: ['anal', 'gay', 'transsexual', 'bisexual', 'pissing', 'anal prolapse'],
};
},
computed: {
tagFilter,
},
methods: {
filterTag,
},
};
</script>
<style lang="scss" scoped>
.dialog-body {
width: 40rem;
max-width: 100%;
}
.filters {
width: 20rem;
max-width: 100%;
}
.tags-item {
display: block;
}
.tag {
padding: .5rem 0;
}
.disclaimer {
margin: 1rem 0 0 0;
line-height: 1.5;
text-align: center;
font-size: .9rem;
color: var(--shadow);
}
</style>

View File

@@ -0,0 +1,81 @@
<template>
<Dialog
title="Settings"
@close="$emit('close')"
>
<nav class="tabs">
<button
class="tab"
:class="{ selected: section === 'filters' }"
@click="section = 'filters'"
>Filters</button>
<button
class="tab"
:class="{ selected: section === 'summary' }"
@click="section = 'summary'"
>Summary</button>
</nav>
<div class="dialog-body">
<component :is="sections[section]" />
</div>
</Dialog>
</template>
<script>
import { shallowRef } from 'vue';
import Filters from './filters.vue';
import Summary from './summary.vue';
export default {
emits: ['close'],
data() {
return {
sections: {
filters: shallowRef(Filters),
summary: shallowRef(Summary),
},
section: 'filters',
};
},
};
</script>
<style lang="scss" scoped>
.dialog-body {
width: 40rem;
max-width: 100%;
}
.tabs {
display: flex;
}
.tab {
flex-grow: 1;
padding: .75rem 1rem;
background: var(--shadow-touch);
border: none;
border-bottom: solid 1px var(--shadow-hint);
color: var(--shadow);
font-size: 1rem;
font-weight: bold;
&:not(:first-child) {
border-left: solid 1px var(--shadow-hint);
}
&.selected {
background: none;
color: var(--primary);
border-bottom: none;
}
&:hover {
color: var(--shadow-strong);
cursor: pointer;
}
}
</style>

View File

@@ -0,0 +1,327 @@
<template>
<div>
<div class="dialog-section">
<h3 class="form-heading">Summary format</h3>
<ul class="summary nolist">
<li
v-for="(group, groupIndex) in summaryFormat"
:key="groupIndex"
class="summary-group"
>
<div class="summary-options">
<label class="summary-option">Delimiter
<input
class="input summary-delimiter"
:value="group.delimiter"
@change="setSummaryGroupValue(groupIndex, 'delimiter', $event.target.value)"
>
</label>
<label class="summary-option">Brackets
<select
class="select summary-delimiter"
:value="group.bracket"
@change="setSummaryGroupValue(groupIndex, 'bracket', $event.target.value)"
>
<option
v-for="bracket in brackets"
:key="bracket"
>{{ bracket }}</option>
</select>
</label>
</div>
<ul class="summary-segments nolist">
<li
v-for="(segment, segmentIndex) in group.segments"
:key="segmentIndex"
class="summary-segment"
>
<select
class="select summary-prop"
:value="segment.prop"
@change="setSummarySegmentValue(groupIndex, segmentIndex, 'prop', $event.target.value)"
>
<option>channel</option>
<option>network</option>
<option>title</option>
<option>movie</option>
<option>tags</option>
<option>actors</option>
<option>date</option>
</select>
<input
v-if="delimitedProps.includes(segment.prop)"
class="input summary-delimiter"
:value="segment.delimiter"
@change="setSummarySegmentValue(groupIndex, segmentIndex, 'delimiter', $event.target.value)"
>
<select
v-if="segment.prop === 'date'"
class="select summary-format"
:value="segment.format"
@change="setSummarySegmentValue(groupIndex, segmentIndex, 'format', $event.target.value)"
>
<option>YYYY-MM-DD</option>
<option>DD-MM-YYYY</option>
<option>MM/DD/YYYY</option>
</select>
<Icon
icon="bin"
class="active"
@click="removeSummarySegment(groupIndex, segmentIndex)"
/>
</li>
<li class="summary-actions">
<button
type="button"
class="button button-secondary"
@click="addSummarySegment(groupIndex)"
>Add segment</button>
<button
type="button"
class="button button-secondary"
@click="removeSummaryGroup(groupIndex)"
>Remove group</button>
</li>
</ul>
</li>
<li class="summary summary-actions">
<button
type="button"
class="button button-secondary"
@click="addSummaryGroup"
>Add group</button>
<button
type="button"
class="button button-secondary"
@click="resetSummaryFormat"
>Reset to default</button>
</li>
</ul>
</div>
<div class="dialog-section">
<h3 class="form-heading">Preview</h3>
<input
class="input summary-preview"
:value="summary"
:title="summary"
disabled
>
</div>
</div>
</template>
<script>
import formatSummary from '../../js/utils/format-summary';
function summary() {
return formatSummary(this.scene, this.summaryFormat);
}
function summaryFormat() {
return this.$store.state.ui.summaryFormat;
}
function setSummaryGroupValue(targetGroupIndex, target, value) {
const newFormat = this.summaryFormat.map((group, groupIndex) => {
if (groupIndex === targetGroupIndex) {
return {
...group,
[target]: value,
};
}
return group;
});
this.$store.dispatch('setSummaryFormat', newFormat);
}
function setSummarySegmentValue(targetGroupIndex, targetSegmentIndex, target, value) {
const newFormat = this.summaryFormat.map((group, groupIndex) => {
if (groupIndex === targetGroupIndex) {
return {
...group,
segments: group.segments.map((segment, segmentIndex) => {
if (segmentIndex === targetSegmentIndex) {
return {
...segment,
[target]: value,
};
}
return segment;
}),
};
}
return group;
});
this.$store.dispatch('setSummaryFormat', newFormat);
}
function addSummarySegment(targetGroupIndex) {
const newFormat = this.summaryFormat.map((group, groupIndex) => {
if (groupIndex === targetGroupIndex) {
return {
...group,
segments: group.segments.concat({
prop: 'title',
delimiter: ',', // default delimiter for when prop is changed to iterabte like actors or tags
format: 'YYYY-MM-DD', // default format for when prop is changed to date
}),
};
}
return group;
});
this.$store.dispatch('setSummaryFormat', newFormat);
}
function addSummaryGroup() {
const newFormat = this.summaryFormat.concat({
delimiter: ' - ',
segments: [{ prop: 'title' }],
});
this.$store.dispatch('setSummaryFormat', newFormat);
}
function removeSummaryGroup(groupIndex) {
const newFormat = this.summaryFormat.filter((group, index) => index !== groupIndex);
this.$store.dispatch('setSummaryFormat', newFormat);
}
function removeSummarySegment(targetGroupIndex, targetSegmentIndex) {
const newFormat = this.summaryFormat.map((group, groupIndex) => ({
...group,
segments: groupIndex === targetGroupIndex
? group.segments.filter((segment, index) => index !== targetSegmentIndex)
: group.segments,
}));
this.$store.dispatch('setSummaryFormat', newFormat);
}
function resetSummaryFormat() {
this.$store.dispatch('setSummaryFormat', this.$store.state.ui.defaultSummaryFormat);
}
export default {
data() {
return {
delimiters: [null, '-', '_', ',', '.'],
brackets: [null, '()', '[]', '{}', '<>'],
delimitedProps: ['actors', 'tags'],
scene: {
channel: 'Channel',
network: 'Network',
title: 'Title',
movie: 'Movie',
scene: 1,
actors: ['Jane Doe', 'John Doe'],
date: new Date(),
},
};
},
computed: {
summary,
summaryFormat,
},
methods: {
addSummaryGroup,
setSummaryGroupValue,
addSummarySegment,
setSummarySegmentValue,
removeSummaryGroup,
removeSummarySegment,
resetSummaryFormat,
},
};
</script>
<style lang="scss" scoped>
.summary {
.icon {
padding: .5rem;
}
}
.summary-group,
.summary-segment {
display: flex;
}
.summary-group {
display: flex;
flex-direction: column;
margin-bottom: .5rem;
.button {
margin-top: .5rem;
}
&:not(:last-child) {
padding-bottom: .5rem;
border-bottom: solid 1px var(--shadow-hint);
margin-bottom: .5rem;
}
}
.summary-segments {
width: 100%;
display: flex;
flex-direction: column;
}
.summary-segment {
display: flex;
align-items: center;
margin-bottom: .25rem;
}
.summary-delimiter {
width: 5rem;
}
.summary-format {
width: 9rem;
}
.summary-prop {
flex-grow: 1;
}
.summary-options {
margin-bottom: .5rem;
}
.summary-option:not(:last-child) {
margin-right: 1rem;
}
.summary-actions {
display: flex;
justify-content: space-between;
align-items: center;
}
.summary-preview {
width: 100%;
margin-bottom: 1rem;
}
</style>