New: UI Updates (Backup Restore in App, Profile Cloning)

UI Pulls from Sonarr
This commit is contained in:
Qstick 2018-01-14 17:11:37 -05:00
parent 80a5701b99
commit 744742b5ff
80 changed files with 2376 additions and 795 deletions

View file

@ -13,7 +13,7 @@ function createFetchSchemaHandler(section, url) {
dispatch(set({
section,
isFetchingSchema: false,
schemaPopulated: true,
isSchemaPopulated: true,
schemaError: null,
schema: data
}));
@ -23,7 +23,7 @@ function createFetchSchemaHandler(section, url) {
dispatch(set({
section,
isFetchingSchema: false,
schemaPopulated: true,
isSchemaPopulated: true,
schemaError: xhr
}));
});

View file

@ -68,7 +68,7 @@ export default {
isPopulated: false,
error: null,
isFetchingSchema: false,
schemaPopulated: false,
isSchemaPopulated: false,
schemaError: null,
schema: [],
selectedSchema: {},

View file

@ -68,7 +68,7 @@ export default {
isPopulated: false,
error: null,
isFetchingSchema: false,
schemaPopulated: false,
isSchemaPopulated: false,
schemaError: null,
schema: [],
selectedSchema: {},

View file

@ -1,5 +1,7 @@
import { createAction } from 'redux-actions';
import { createThunk } from 'Store/thunks';
import getSectionState from 'Utilities/State/getSectionState';
import updateSectionState from 'Utilities/State/updateSectionState';
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
@ -19,6 +21,7 @@ export const FETCH_LANGUAGE_PROFILE_SCHEMA = 'settings/languageProfiles/fetchLan
export const SAVE_LANGUAGE_PROFILE = 'settings/languageProfiles/saveLanguageProfile';
export const DELETE_LANGUAGE_PROFILE = 'settings/languageProfiles/deleteLanguageProfile';
export const SET_LANGUAGE_PROFILE_VALUE = 'settings/languageProfiles/setLanguageProfileValue';
export const CLONE_LANGUAGE_PROFILE = 'settings/languageProfiles/cloneLanguageProfile';
//
// Action Creators
@ -35,6 +38,8 @@ export const setLanguageProfileValue = createAction(SET_LANGUAGE_PROFILE_VALUE,
};
});
export const cloneLanguageProfile = createAction(CLONE_LANGUAGE_PROFILE);
//
// Details
@ -50,7 +55,7 @@ export default {
isDeleting: false,
deleteError: null,
isFetchingSchema: false,
schemaPopulated: false,
isSchemaPopulated: false,
schemaError: null,
schema: {},
isSaving: false,
@ -73,7 +78,20 @@ export default {
// Reducers
reducers: {
[SET_LANGUAGE_PROFILE_VALUE]: createSetSettingValueReducer(section)
[SET_LANGUAGE_PROFILE_VALUE]: createSetSettingValueReducer(section),
[CLONE_LANGUAGE_PROFILE]: function(state, { payload }) {
const id = payload.id;
const newState = getSectionState(state, section);
const item = newState.items.find((i) => i.id === id);
const pendingChanges = { ...item, id: 0 };
delete pendingChanges.id;
pendingChanges.name = `${pendingChanges.name} - Copy`;
newState.pendingChanges = pendingChanges;
return updateSectionState(state, section, newState);
}
}
};

View file

@ -1,5 +1,7 @@
import { createAction } from 'redux-actions';
import { createThunk } from 'Store/thunks';
import getSectionState from 'Utilities/State/getSectionState';
import updateSectionState from 'Utilities/State/updateSectionState';
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
@ -19,6 +21,7 @@ export const FETCH_METADATA_PROFILE_SCHEMA = 'settings/metadataProfiles/fetchMet
export const SAVE_METADATA_PROFILE = 'settings/metadataProfiles/saveMetadataProfile';
export const DELETE_METADATA_PROFILE = 'settings/metadataProfiles/deleteMetadataProfile';
export const SET_METADATA_PROFILE_VALUE = 'settings/metadataProfiles/setMetadataProfileValue';
export const CLONE_METADATA_PROFILE = 'settings/metadataProfiles/cloneMetadataProfile';
//
// Action Creators
@ -35,6 +38,8 @@ export const setMetadataProfileValue = createAction(SET_METADATA_PROFILE_VALUE,
};
});
export const cloneMetadataProfile = createAction(CLONE_METADATA_PROFILE);
//
// Details
@ -50,7 +55,7 @@ export default {
isDeleting: false,
deleteError: null,
isFetchingSchema: false,
schemaPopulated: false,
isSchemaPopulated: false,
schemaError: null,
schema: {},
isSaving: false,
@ -73,7 +78,20 @@ export default {
// Reducers
reducers: {
[SET_METADATA_PROFILE_VALUE]: createSetSettingValueReducer(section)
[SET_METADATA_PROFILE_VALUE]: createSetSettingValueReducer(section),
[CLONE_METADATA_PROFILE]: function(state, { payload }) {
const id = payload.id;
const newState = getSectionState(state, section);
const item = newState.items.find((i) => i.id === id);
const pendingChanges = { ...item, id: 0 };
delete pendingChanges.id;
pendingChanges.name = `${pendingChanges.name} - Copy`;
newState.pendingChanges = pendingChanges;
return updateSectionState(state, section, newState);
}
}
};

View file

@ -68,7 +68,7 @@ export default {
isPopulated: false,
error: null,
isFetchingSchema: false,
schemaPopulated: false,
isSchemaPopulated: false,
schemaError: null,
schema: [],
selectedSchema: {},

View file

@ -1,5 +1,7 @@
import { createAction } from 'redux-actions';
import { createThunk } from 'Store/thunks';
import getSectionState from 'Utilities/State/getSectionState';
import updateSectionState from 'Utilities/State/updateSectionState';
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
@ -19,6 +21,7 @@ export const FETCH_QUALITY_PROFILE_SCHEMA = 'settings/qualityProfiles/fetchQuali
export const SAVE_QUALITY_PROFILE = 'settings/qualityProfiles/saveQualityProfile';
export const DELETE_QUALITY_PROFILE = 'settings/qualityProfiles/deleteQualityProfile';
export const SET_QUALITY_PROFILE_VALUE = 'settings/qualityProfiles/setQualityProfileValue';
export const CLONE_QUALITY_PROFILE = 'settings/qualityProfiles/cloneQualityProfile';
//
// Action Creators
@ -35,6 +38,8 @@ export const setQualityProfileValue = createAction(SET_QUALITY_PROFILE_VALUE, (p
};
});
export const cloneQualityProfile = createAction(CLONE_QUALITY_PROFILE);
//
// Details
@ -50,7 +55,7 @@ export default {
isDeleting: false,
deleteError: null,
isFetchingSchema: false,
schemaPopulated: false,
isSchemaPopulated: false,
schemaError: null,
schema: {},
isSaving: false,
@ -73,7 +78,20 @@ export default {
// Reducers
reducers: {
[SET_QUALITY_PROFILE_VALUE]: createSetSettingValueReducer(section)
[SET_QUALITY_PROFILE_VALUE]: createSetSettingValueReducer(section),
[CLONE_QUALITY_PROFILE]: function(state, { payload }) {
const id = payload.id;
const newState = getSectionState(state, section);
const item = newState.items.find((i) => i.id === id);
const pendingChanges = { ...item, id: 0 };
delete pendingChanges.id;
pendingChanges.name = `${pendingChanges.name} - Copy`;
newState.pendingChanges = pendingChanges;
return updateSectionState(state, section, newState);
}
}
};

View file

@ -36,6 +36,7 @@ export const defaultState = {
isConnected: true,
isReconnecting: false,
isDisconnected: false,
isRestarting: false,
isSidebarVisible: !getDimensions(window.innerWidth, window.innerHeight).isSmallScreen
};

View file

@ -3,15 +3,19 @@ import { createAction } from 'redux-actions';
import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
import { sortDirections } from 'Helpers/Props';
import { createThunk, handleThunks } from 'Store/thunks';
import { setAppValue } from 'Store/Actions/appActions';
import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
import createFetchHandler from './Creators/createFetchHandler';
import createRemoveItemHandler from './Creators/createRemoveItemHandler';
import createHandleActions from './Creators/createHandleActions';
import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers';
import { set } from './baseActions';
//
// Variables
export const section = 'system';
const backupsSection = 'system.backups';
//
// State
@ -49,6 +53,10 @@ export const defaultState = {
isFetching: false,
isPopulated: false,
error: null,
isRestoring: false,
restoreError: null,
isDeleting: false,
deleteError: null,
items: []
},
@ -135,7 +143,12 @@ export const FETCH_DISK_SPACE = 'system/diskSpace/fetchDiskSPace';
export const FETCH_TASK = 'system/tasks/fetchTask';
export const FETCH_TASKS = 'system/tasks/fetchTasks';
export const FETCH_BACKUPS = 'system/backups/fetchBackups';
export const RESTORE_BACKUP = 'system/backups/restoreBackup';
export const CLEAR_RESTORE_BACKUP = 'system/backups/clearRestoreBackup';
export const DELETE_BACKUP = 'system/backups/deleteBackup';
export const FETCH_UPDATES = 'system/updates/fetchUpdates';
export const FETCH_LOGS = 'system/logs/fetchLogs';
@ -163,7 +176,12 @@ export const fetchDiskSpace = createThunk(FETCH_DISK_SPACE);
export const fetchTask = createThunk(FETCH_TASK);
export const fetchTasks = createThunk(FETCH_TASKS);
export const fetchBackups = createThunk(FETCH_BACKUPS);
export const restoreBackup = createThunk(RESTORE_BACKUP);
export const clearRestoreBackup = createAction(CLEAR_RESTORE_BACKUP);
export const deleteBackup = createThunk(DELETE_BACKUP);
export const fetchUpdates = createThunk(FETCH_UPDATES);
export const fetchLogs = createThunk(FETCH_LOGS);
@ -191,7 +209,72 @@ export const actionHandlers = handleThunks({
[FETCH_DISK_SPACE]: createFetchHandler('system.diskSpace', '/diskspace'),
[FETCH_TASK]: createFetchHandler('system.tasks', '/system/task'),
[FETCH_TASKS]: createFetchHandler('system.tasks', '/system/task'),
[FETCH_BACKUPS]: createFetchHandler('system.backups', '/system/backup'),
[FETCH_BACKUPS]: createFetchHandler(backupsSection, '/system/backup'),
[RESTORE_BACKUP]: function(getState, payload, dispatch) {
const {
id,
file
} = payload;
dispatch(set({
section: backupsSection,
isRestoring: true
}));
let ajaxOptions = null;
if (id) {
ajaxOptions = {
url: `/system/backup/restore/${id}`,
method: 'POST',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify({
id
})
};
} else if (file) {
const formData = new FormData();
formData.append('restore', file);
ajaxOptions = {
url: '/system/backup/restore/upload',
method: 'POST',
processData: false,
contentType: false,
data: formData
};
} else {
dispatch(set({
section: backupsSection,
isRestoring: false,
restoreError: 'Error restoring backup'
}));
}
const promise = $.ajax(ajaxOptions);
promise.done((data) => {
dispatch(set({
section: backupsSection,
isRestoring: false,
restoreError: null
}));
});
promise.fail((xhr) => {
dispatch(set({
section: backupsSection,
isRestoring: false,
restoreError: xhr
}));
});
},
[DELETE_BACKUP]: createRemoveItemHandler(backupsSection, '/system/backup'),
[FETCH_UPDATES]: createFetchHandler('system.updates', '/update'),
[FETCH_LOG_FILES]: createFetchHandler('system.logFiles', '/log/file'),
[FETCH_UPDATE_LOG_FILES]: createFetchHandler('system.updateLogFiles', '/log/file/update'),
@ -212,11 +295,15 @@ export const actionHandlers = handleThunks({
}
),
[RESTART]: function() {
$.ajax({
[RESTART]: function(getState, payload, dispatch) {
const promise = $.ajax({
url: '/system/restart',
method: 'POST'
});
promise.done(() => {
dispatch(setAppValue({ isRestarting: true }));
});
},
[SHUTDOWN]: function() {
@ -232,6 +319,17 @@ export const actionHandlers = handleThunks({
export const reducers = createHandleActions({
[CLEAR_RESTORE_BACKUP]: function(state, { payload }) {
return {
...state,
backups: {
...state.backups,
isRestoring: false,
restoreError: null
}
};
},
[SET_LOGS_TABLE_OPTION]: createSetTableOptionReducer('logs')
}, defaultState, section);