Skip to content
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

Add subtitle search SFC #6727

Merged
merged 25 commits into from
Jun 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e0695d1
Add SFC subtitle-search.vue
p0psicles May 25, 2019
ce17f32
Add the component itself.
p0psicles May 25, 2019
3afb8e8
Add jest test
p0psicles May 25, 2019
754001e
Merge remote-tracking branch 'remotes/origin/develop' into feature/ad…
p0psicles May 26, 2019
cd8c922
Add new fixtures for jest tests.
p0psicles May 27, 2019
6740348
Added jest test for subtitle-search.vue component.
p0psicles May 27, 2019
63642d0
Added snapshot
p0psicles May 29, 2019
025366d
Fix eslint warnings.
p0psicles May 29, 2019
9be825f
Utilize the vue destroyed() method.
p0psicles May 29, 2019
e31e5f0
Merge remote-tracking branch 'remotes/origin/develop' into feature/ad…
p0psicles May 29, 2019
a77a3b9
Yarn dev after rebase.
p0psicles May 29, 2019
3c9abf0
* Implement review comments.
p0psicles May 30, 2019
c21052a
use computed instead of method, to create the params.
p0psicles May 30, 2019
6aabce1
Revert changes back making the component destroy itself (remove child…
p0psicles Jun 1, 2019
1c32bd7
Remove 'this'.
p0psicles Jun 1, 2019
b7dce65
Merge branch 'develop' into feature/add-subtitle-search-sfc
p0psicles Jun 2, 2019
a131dd3
Merge remote-tracking branch 'remotes/origin/develop' into feature/ad…
p0psicles Jun 5, 2019
cab1ca5
Update subtitle-search.vue snapshots.
p0psicles Jun 5, 2019
3c72e89
linting
p0psicles Jun 5, 2019
6193880
build
p0psicles Jun 5, 2019
7d8adc5
Remove comment at top of file
p0psicles Jun 5, 2019
9cda490
Fix `date-fns` getting bundled twice
sharkykh Jun 6, 2019
8b33d3c
Split `date-fns` to a separate bundle
sharkykh Jun 6, 2019
210f456
Remove unused eslint disable comments
sharkykh Jun 6, 2019
f6fecd1
Lint
sharkykh Jun 6, 2019
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
4 changes: 4 additions & 0 deletions themes-default/slim/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
}
}
},
"resolutions": {
"**/jquery": "3.4.1",
"**/date-fns": "2.0.0-alpha.29"
},
"dependencies": {
"axios": "0.19.0",
"bootstrap": "3.4.1",
Expand Down
1 change: 1 addition & 0 deletions themes-default/slim/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ export { default as ShowHeader } from './show-header.vue';
export { default as SnatchSelection } from './snatch-selection.vue';
export { default as Status } from './status.vue';
export { default as SubMenu } from './sub-menu.vue';
export { default as SubtitleSearch } from './subtitle-search.vue';
export * from './http';
export * from './helpers';
262 changes: 262 additions & 0 deletions themes-default/slim/src/components/subtitle-search.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
<template>
<tr class="subtitle-search-wrapper">
<td colspan="9999">
<span v-if="loading" class="loading-message">{{loadingMessage}} <state-switch :theme="config.themeName" state="loading" /></span>
<div v-if="displayQuestion" class="search-question">
<div class="question">
<p>Do you want to manually pick subtitles or let us choose it for you?</p>
</div>
<div class="options">
<button type="button" class="btn-medusa btn-info" @click="autoSearch">Auto</button>
<button type="button" class="btn-medusa btn-success" @click="manualSearch">Manual</button>
</div>
</div>

<vue-good-table v-if="subtitles.length > 0"
:columns="columns"
:rows="subtitles"
:search-options="{
enabled: false
}"
:sort-options="{
enabled: true,
initialSortBy: { field: 'score', type: 'desc' }
}"
styleClass="vgt-table condensed subtitle-table"
>
<template v-slot:table-column="props">
<span v-if="props.column.label === 'Download'">
<span>{{props.column.label}}</span>
<span class="btn-medusa btn-xs pull-right" @click="close">hide</span>
</span>
<span v-else>
{{props.column.label}}
</span>
</template>
<template v-slot:table-row="props">
<span v-if="props.column.field === 'provider'">
<img :src="`images/subtitles/${props.row.provider}.png`" width="16" height="16" />
<span :title="props.row.provider">{{props.row.provider}}</span>
</span>
<span v-else-if="props.column.field === 'lang'">
<img :title="props.row.lang" :src="`images/subtitles/flags/${props.row.lang}.png`" width="16" height="11" />
</span>
<span v-else-if="props.column.field === 'filename'">
<a :title="`Download${props.row.hearing_impaired ? ' hearing impaired ' : ' '}subtitle: ${props.row.filename}`" @click="pickSubtitle(props.row.id)">
<img v-if="props.row.hearing_impaired" src="images/hearing_impaired.png" width="16" height="16" />
<span class="subtitle-name">{{props.row.filename}}</span>
<img v-if="props.row.sub_score >= props.row.min_score" src="images/save.png" width="16" height="16" />
</a>
</span>
<span v-else-if="props.column.field === 'download'">
<a :title="`Download${props.row.hearing_impaired ? ' hearing impaired ' : ' '}subtitle: ${props.row.filename}`" @click="pickSubtitle(props.row.id)">
<img src="images/download.png" width="16" height="16" />
</a>
</span>
<span v-else>
{{props.formattedRow[props.column.field]}}
</span>
</template>
</vue-good-table>
</td>
</tr>
</template>
<script>

import { mapState } from 'vuex';
import { VueGoodTable } from 'vue-good-table';
p0psicles marked this conversation as resolved.
Show resolved Hide resolved
import { apiRoute } from '../api';
import { StateSwitch } from './helpers';

export default {
name: 'subtitle-search',
components: {
StateSwitch,
VueGoodTable
p0psicles marked this conversation as resolved.
Show resolved Hide resolved
},
props: {
show: {
type: Object,
required: true
},
season: {
type: [String, Number],
required: true
},
episode: {
type: [String, Number],
required: true
}
},
data() {
return {
columns: [{
label: 'Filename',
field: 'filename'
}, {
label: 'Language',
field: 'lang'
}, {
label: 'Provider',
field: 'provider'
}, {
label: 'Score',
field: 'score',
type: 'number'
}, {
label: 'Sub Score',
field: 'sub_score',
type: 'number'
}, {
label: 'Missing Matches',
field: rowObj => {
if (rowObj.missing_guess) {
return rowObj.missing_guess.join(', ');
}
},
type: 'array'
}, {
label: 'Download',
field: 'download',
sortable: false
}],
subtitles: [],
displayQuestion: false,
loading: false,
loadingMessage: ''
};
},
computed: {
...mapState({
config: state => state.config
}),
subtitleParams() {
const { episode, show, season } = this;
const params = {
indexername: show.indexer,
seriesid: show.id[show.indexer],
season,
episode
};

return params;
}
},
mounted() {
this.displayQuestion = true;
},
methods: {
autoSearch() {
const { subtitleParams } = this;

this.displayQuestion = false;
this.loadingMessage = 'Searching for subtitles and downloading if available... ';
this.loading = true;
apiRoute('home/searchEpisodeSubtitles', { params: subtitleParams })
.then(response => {
if (response.data.result !== 'failure') {
// Update the show, as we have new information (subtitles)
// Let's emit an event, telling the displayShow component, to update the show using the api/store.
this.$emit('update', {
reason: 'new subtitles found',
codes: response.data.subtitles,
languages: response.data.languages
});
}
})
.catch(error => {
console.log(`Error trying to search for subtitles. Error: ${error}`);
})
.finally(() => {
// Cleanup
this.loadingMessage = '';
this.loading = false;
this.close();
});
},
manualSearch() {
const { subtitleParams } = this;

this.displayQuestion = false;
this.loading = true;
this.loadingMessage = 'Searching for subtitles... ';
apiRoute('home/manualSearchSubtitles', { params: subtitleParams })
.then(response => {
if (response.data.result === 'success') {
this.subtitles.push(...response.data.subtitles);
}
}).catch(error => {
console.log(`Error trying to search for subtitles. Error: ${error}`);
}).finally(() => {
this.loading = false;
});
},
pickSubtitle(subtitleId) {
// Download and save this subtitle with the episode.
const { subtitleParams } = this;
const params = {
...subtitleParams,
picked_id: subtitleId // eslint-disable-line camelcase
};

this.displayQuestion = false;
this.loadingMessage = 'downloading subtitle... ';
this.loading = true;

apiRoute('home/manualSearchSubtitles', { params })
.then(response => {
if (response.data.result === 'success') {
// Update the show, as we have new information (subtitles)
// Let's emit an event, telling the displayShow component, to update the show using the api/store.
this.$emit('update', {
reason: 'new subtitles found',
codes: response.data.subtitles,
languages: response.data.languages
});
}
})
.catch(error => {
console.log(`Error trying to search for subtitles. Error: ${error}`);
})
.finally(() => {
// Cleanup
this.loadingMessage = '';
this.loading = false;
this.close();
});
},
close() {
this.$emit('close');
// Destroy the vue listeners, etc
this.$destroy();
// Remove the element from the DOM
this.$el.parentNode.removeChild(this.$el);
}
}
};
</script>
<style scoped>
.subtitle-search-wrapper {
display: table-row;
column-span: all;
}

.subtitle-search-wrapper >>> table.subtitle-table tr {
background-color: rgb(190, 222, 237);
}

.subtitle-search-wrapper > td {
padding: 0;
}

.search-question, .loading-message {
background-color: rgb(51, 51, 51);
color: rgb(255,255,255);
padding: 10px;
line-height: 55px;
}

span.subtitle-name {
color: rgb(0, 0, 0);
}
</style>
Loading