@@ -507,6 +561,7 @@
$('#series_nav').addClass("active");
seriesDetailsRefresh();
+ episodesDetailsRefresh();
getLanguages();
getEnabledLanguages();
@@ -961,6 +1016,326 @@
});
});
+ const UploadStatus = {
+ ERROR: 0,
+ VALID: 1,
+ UPLOAD: 2,
+ DONE: 3
+ }
+
+ $('#mass_upload_button').on('click', function (e) {
+ e.preventDefault();
+
+ $('#upload_table').DataTable({
+ destroy: true,
+ processing: true,
+ language: {
+ zeroRecords: 'Select Subtitles to Get Started',
+ processing: "Loading Subtitle..."
+ },
+ searching: false,
+ ordering: false,
+ lengthChange: false,
+ serverSide: false,
+ responsive: true,
+ columns: [
+ {
+ data: null,
+ render: function(data, type, row) {
+ switch (data.status) {
+ case UploadStatus.VALID:
+ return '
'
+ case UploadStatus.UPLOAD:
+ return '
'
+ case UploadStatus.DONE:
+ return '
'
+ case UploadStatus.ERROR:
+ default:
+ return '
'
+ }
+ }
+ },
+ {data: 'filename'},
+ {
+ data: "season",
+ render: function(data, type, row) {
+ let cls = []
+ let readonly = false
+ if (data <= 0) {
+ if (row.status !== UploadStatus.UPLOAD) {
+ cls.push('is-invalid');
+ } else {
+ readonly = true
+ }
+ } else {
+ if (row.status === UploadStatus.UPLOAD) {
+ readonly = true;
+ }
+ }
+ return `
`
+ }
+ },
+ {
+ data: "episode",
+ render: function(data, type, row) {
+ let cls = []
+ let readonly = false
+ if (data <= 0) {
+ if (row.status !== UploadStatus.UPLOAD) {
+ cls.push('is-invalid');
+ } else {
+ readonly = true
+ }
+ } else {
+ if (row.status === UploadStatus.UPLOAD) {
+ readonly = true;
+ }
+ }
+ return `
`
+ }
+ },
+ {
+ data: null,
+ render: function(data, type, row) {
+ return `
`
+ }
+ }
+ ]
+ })
+
+ // reset
+ $('#upload_table').DataTable().table().clear().draw();
+ $('#mass_upload_file_list').val("")
+ $('#mass-upload-file-label').text('Choose files')
+
+ $("#mass_upload_title_span")
+ .html(`${seriesDetails['title']} - Upload`);
+
+ $('#mass_upload_language_select')
+ .empty();
+ $.each(enabledLanguages, function (i, item) {
+ $('#mass_upload_language_select')
+ .append(`
`);
+ });
+ $("#mass_upload_language_select")
+ .selectpicker("refresh");
+
+ $('#mass_upload_forced_checkbox')
+ .val(seriesDetails['forced'])
+ .change();
+
+ $('#massUploadModal')
+ .modal({
+ focus: false
+ });
+ });
+
+ $('#upload_table').on('click', '.mass-upload-del-button', function(e) {
+ e.preventDefault();
+ $('#upload_table').DataTable()
+ .row($(this).parents('tr'))
+ .remove()
+ .draw();
+ });
+
+ $('#upload_table').on('change', '.mass-upload-season-input', function(e) {
+ const value = $(this).val();
+
+ let row = $('#upload_table').DataTable().row($(this).parents('tr'));
+ let data = row.data();
+ data.season = value;
+
+ data.status = UploadStatus.ERROR;
+ for(const exist of episodesDetails.data) {
+ if (exist.episode == data.episode && exist.season == data.season) {
+ data.status = UploadStatus.VALID;
+ data.exist = exist
+ break;
+ }
+ }
+
+ row.data(data).draw()
+ })
+
+ $('#upload_table').on('change', '.mass-upload-episode-input', function(e) {
+ const value = $(this).val();
+
+ let row = $('#upload_table').DataTable().row($(this).parents('tr'));
+ let data = row.data();
+ data.episode = value;
+
+ data.status = UploadStatus.ERROR;
+ for(const exist of episodesDetails.data) {
+ if (exist.episode == data.episode && exist.season == data.season) {
+ data.status = UploadStatus.VALID;
+ data.exist = exist
+ break;
+ }
+ }
+
+ row.data(data).draw()
+ })
+
+ $('#mass_upload_file_list').change(function() {
+ let filelist = $('#mass_upload_file_list').get(0).files
+ $('#mass-upload-file-label').text(`${filelist.length} Files`)
+
+ $('#mass_upload_save_button').prop('disabled', true)
+ $('#mass_upload_close_btn').prop('disabled', true);
+ $('#mass_upload_cancel_btn').prop('disabled', true);
+
+ let table = $('#upload_table').DataTable();
+
+ table.table().clear().draw();
+
+ const episodes = episodesDetails.data
+
+ let promiselist = []
+
+ for (const file of filelist) {
+ const name = file.name;
+
+ const object = {
+ file: file,
+ filename: name,
+ season: 0,
+ episode: 0,
+ status: UploadStatus.UPLOAD,
+ exist: null
+ }
+
+ const cacheRow = table.row.add(object)
+
+ promiselist.push(Promise.resolve($.ajax({
+ url: "{{ url_for('api.subtitlenameinfo') }}",
+ type: "GET",
+ dataType: "json",
+ data: {
+ filename: name
+ },
+ complete: function(data) {
+ const response = data.responseJSON.data;
+ const season = (response.season ?? 1);
+
+ let existdata = null
+ for(const exist of episodes) {
+ if (exist.episode == response.episode && exist.season == season) {
+ existdata = exist;
+ break;
+ }
+ }
+
+ let complete = {
+ file: file,
+ filename: name,
+ season: season,
+ episode: response.episode ?? 0,
+ status: existdata != null ? UploadStatus.VALID : UploadStatus.ERROR,
+ exist: existdata,
+ row: cacheRow
+ };
+ table.row(cacheRow).data(complete)
+ .draw();
+
+ },
+ error: function(data) {
+ let error = {
+ file: file,
+ filename: name,
+ season: 0,
+ episode: 0,
+ status: UploadStatus.ERROR,
+ exist: null,
+ row: cacheRow
+ };
+ table.row(cacheRow).data(error)
+ .draw();
+ }
+ })))
+ }
+
+ table.table().draw();
+
+ Promise.all(promiselist)
+ .then(function(){
+ $('#mass_upload_save_button').prop('disabled', false)
+ $('#mass_upload_close_btn').prop('disabled', false);
+ $('#mass_upload_cancel_btn').prop('disabled', false);
+ })
+ })
+
+ $('#mass_upload_form').on('submit', function(e) {
+ e.preventDefault();
+ $('#mass_upload_save_button').html('
');
+
+ const formdata = new FormData(document.getElementById("mass_upload_form"));
+
+ const language = formdata.get("language");
+
+ let table = $('#upload_table').DataTable();
+
+ const uploadlist = table.data().toArray().filter(function(item) {
+ return item.status === UploadStatus.VALID
+ });
+
+ const promiselist = uploadlist.map(function(item) {
+ const data = {
+ sonarrSeriesId: item.exist.sonarrSeriesId,
+ sonarrEpisodeId: item.exist.sonarrEpisodeId,
+ language: language,
+ upload: item.file,
+ episodePath: item.exist.mapped_path,
+ // sceneName,
+ title: item.exist.title,
+ audioLanguage: item.exist.audio_language.name,
+ forced: false
+ }
+
+ const form = new FormData()
+ for(const key in data) {
+ form.append(key, data[key])
+ }
+
+ const cacheRow = item.row ?? null
+
+ item.status = UploadStatus.UPLOAD;
+
+ let row = table.row(cacheRow);
+
+ row.data(item).draw()
+
+ return Promise.resolve($.ajax({
+ url: "{{ url_for('api.episodessubtitlesupload') }}",
+ data: form,
+ processData: false,
+ contentType: false,
+ type: 'POST',
+ complete: function(e) {
+ item.status = UploadStatus.DONE;
+ row.data(item).draw()
+ },
+ error: function(e) {
+ item.status = UploadStatus.ERROR;
+ row.data(item).draw()
+ }
+ }));
+ })
+
+ Promise.all(promiselist)
+ .then(function(){
+ $('#massUploadModal').modal('hide');
+ })
+ .catch(function() {
+ })
+ .finally(function() {
+ $('#mass_upload_save_button').html('Upload');
+ })
+ })
+
$('#edit_button').on('click', function (e) {
e.preventDefault();
$("#edit_series_title_span").html(seriesDetails['title']);
@@ -1413,6 +1788,21 @@
});
+ function episodesDetailsRefresh() {
+ $.ajax({
+ url: "{{ url_for('api.episodes') }}",
+ type: "GET",
+ dataType: "json",
+ data: {
+ seriesid: "{{id}}",
+ },
+ complete: function(data) {
+ const response = data.responseJSON;
+ episodesDetails = response
+ }
+ })
+ }
+
function seriesDetailsRefresh() {
$.ajax({
url: "{{ url_for('api.series') }}?seriesid={{id}}"