Migrate wizard pages to dedicated app

This commit is contained in:
Bill Thornton
2025-03-31 17:32:54 -04:00
parent dbb0941fef
commit 64b79ec65c
18 changed files with 127 additions and 125 deletions
@@ -0,0 +1,18 @@
<div id="wizardFinishPage" data-role="page" class="page standalonePage wizardPage">
<div class="padded-left padded-right padded-top">
<div class="ui-corner-all ui-shadow wizardContent">
<h1>${LabelYoureDone}</h1>
<p style="margin:2em 0;">${WizardCompleted}</p>
<div class="wizardNavigation">
<button is="emby-button" type="button" class="raised button-cancel" onclick="history.back();">
<span class="material-icons arrow_back" aria-hidden="true"></span>
<span>${Previous}</span>
</button>
<button is="emby-button" type="button" class="raised btnWizardNext button-submit">
<span class="material-icons check" aria-hidden="true"></span>
<span>${LabelFinish}</span>
</button>
</div>
</div>
</div>
</div>
@@ -0,0 +1,16 @@
import loading from 'components/loading/loading';
function onFinish() {
loading.show();
ApiClient.ajax({
url: ApiClient.getUrl('Startup/Complete'),
type: 'POST'
}).then(function () {
loading.hide();
window.location.href = 'index.html';
});
}
export default function (view) {
view.querySelector('.btnWizardNext').addEventListener('click', onFinish);
}
+24
View File
@@ -0,0 +1,24 @@
<div id="wizardLibraryPage" data-role="page" class="page standalonePage wizardPage mediaLibraryPage">
<div class="padded-left padded-right padded-top">
<div class="ui-corner-all ui-shadow wizardContent">
<div>
<h1 style="display:inline-block;">${HeaderSetupLibrary}</h1>
<a href="https://jellyfin.org/docs/general/server/libraries" rel="noopener noreferrer" target="_blank" class="clearLink" style="margin-top:-10px;display:inline-block;vertical-align:middle;margin-left:2em;"><button is="emby-button" type="button" class="raised"><span class="material-icons info" aria-hidden="true"></span><span>${Help}</span></button></a>
</div>
<br />
<div id="divVirtualFolders"></div>
<br />
<br />
<div class="wizardNavigation">
<button is="emby-button" type="button" class="raised button-cancel" onclick="history.back();">
<span class="material-icons arrow_back" aria-hidden="true"></span>
<span>${Previous}</span>
</button>
<button is="emby-button" type="button" class="raised button-submit" onclick="WizardLibraryPage.next();">
<span>${Next}</span>
<span class="material-icons arrow_forward" aria-hidden="true"></span>
</button>
</div>
</div>
</div>
</div>
+388
View File
@@ -0,0 +1,388 @@
import escapeHtml from 'escape-html';
import taskButton from 'scripts/taskbutton';
import loading from 'components/loading/loading';
import globalize from 'lib/globalize';
import dom from 'scripts/dom';
import imageHelper from 'utils/image';
import 'components/cardbuilder/card.scss';
import 'elements/emby-itemrefreshindicator/emby-itemrefreshindicator';
import Dashboard, { pageClassOn, pageIdOn } from 'utils/dashboard';
import confirm from 'components/confirm/confirm';
import { getDefaultBackgroundClass } from 'components/cardbuilder/cardBuilderUtils';
function addVirtualFolder(page) {
import('components/mediaLibraryCreator/mediaLibraryCreator').then(({ default: MediaLibraryCreator }) => {
new MediaLibraryCreator({
collectionTypeOptions: getCollectionTypeOptions().filter(function (f) {
return !f.hidden;
}),
refresh: shouldRefreshLibraryAfterChanges(page)
}).then(function (hasChanges) {
if (hasChanges) {
reloadLibrary(page);
}
});
});
}
function editVirtualFolder(page, virtualFolder) {
import('components/mediaLibraryEditor/mediaLibraryEditor').then(({ default: MediaLibraryEditor }) => {
new MediaLibraryEditor({
refresh: shouldRefreshLibraryAfterChanges(page),
library: virtualFolder
}).then(function (hasChanges) {
if (hasChanges) {
reloadLibrary(page);
}
});
});
}
function deleteVirtualFolder(page, virtualFolder) {
let msg = globalize.translate('MessageAreYouSureYouWishToRemoveMediaFolder');
if (virtualFolder.Locations.length) {
msg += '<br/><br/>' + globalize.translate('MessageTheFollowingLocationWillBeRemovedFromLibrary') + '<br/><br/>';
msg += virtualFolder.Locations.join('<br/>');
}
confirm({
text: msg,
title: globalize.translate('HeaderRemoveMediaFolder'),
confirmText: globalize.translate('Delete'),
primary: 'delete'
}).then(function () {
const refreshAfterChange = shouldRefreshLibraryAfterChanges(page);
ApiClient.removeVirtualFolder(virtualFolder.Name, refreshAfterChange).then(function () {
reloadLibrary(page);
});
});
}
function refreshVirtualFolder(page, virtualFolder) {
import('components/refreshdialog/refreshdialog').then(({ default: RefreshDialog }) => {
new RefreshDialog({
itemIds: [virtualFolder.ItemId],
serverId: ApiClient.serverId(),
mode: 'scan'
}).show();
});
}
function renameVirtualFolder(page, virtualFolder) {
import('components/prompt/prompt').then(({ default: prompt }) => {
prompt({
label: globalize.translate('LabelNewName'),
description: globalize.translate('MessageRenameMediaFolder'),
confirmText: globalize.translate('ButtonRename')
}).then(function (newName) {
if (newName && newName != virtualFolder.Name) {
const refreshAfterChange = shouldRefreshLibraryAfterChanges(page);
ApiClient.renameVirtualFolder(virtualFolder.Name, newName, refreshAfterChange).then(function () {
reloadLibrary(page);
});
}
});
});
}
function showCardMenu(page, elem, virtualFolders) {
const card = dom.parentWithClass(elem, 'card');
const index = parseInt(card.getAttribute('data-index'), 10);
const virtualFolder = virtualFolders[index];
const menuItems = [];
menuItems.push({
name: globalize.translate('EditImages'),
id: 'editimages',
icon: 'photo'
});
menuItems.push({
name: globalize.translate('ManageLibrary'),
id: 'edit',
icon: 'folder'
});
menuItems.push({
name: globalize.translate('ButtonRename'),
id: 'rename',
icon: 'mode_edit'
});
menuItems.push({
name: globalize.translate('ScanLibrary'),
id: 'refresh',
icon: 'refresh'
});
menuItems.push({
name: globalize.translate('ButtonRemove'),
id: 'delete',
icon: 'delete'
});
import('components/actionSheet/actionSheet').then((actionsheet) => {
actionsheet.show({
items: menuItems,
positionTo: elem,
callback: function (resultId) {
switch (resultId) {
case 'edit':
editVirtualFolder(page, virtualFolder);
break;
case 'editimages':
editImages(page, virtualFolder);
break;
case 'rename':
renameVirtualFolder(page, virtualFolder);
break;
case 'delete':
deleteVirtualFolder(page, virtualFolder);
break;
case 'refresh':
refreshVirtualFolder(page, virtualFolder);
}
}
});
});
}
function reloadLibrary(page) {
loading.show();
ApiClient.getVirtualFolders().then(function (result) {
reloadVirtualFolders(page, result);
});
}
function shouldRefreshLibraryAfterChanges(page) {
return page.id === 'mediaLibraryPage';
}
function reloadVirtualFolders(page, virtualFolders) {
let html = '';
virtualFolders.push({
Name: globalize.translate('ButtonAddMediaLibrary'),
icon: 'add_circle',
Locations: [],
showType: false,
showLocations: false,
showMenu: false,
showNameWithIcon: false,
elementId: 'addLibrary'
});
for (let i = 0; i < virtualFolders.length; i++) {
const virtualFolder = virtualFolders[i];
html += getVirtualFolderHtml(page, virtualFolder, i);
}
const divVirtualFolders = page.querySelector('#divVirtualFolders');
divVirtualFolders.innerHTML = html;
divVirtualFolders.classList.add('itemsContainer');
divVirtualFolders.classList.add('vertical-wrap');
const btnCardMenuElements = divVirtualFolders.querySelectorAll('.btnCardMenu');
btnCardMenuElements.forEach(function (btn) {
btn.addEventListener('click', function () {
showCardMenu(page, btn, virtualFolders);
});
});
divVirtualFolders.querySelector('#addLibrary').addEventListener('click', function () {
addVirtualFolder(page);
});
const libraryEditElements = divVirtualFolders.querySelectorAll('.editLibrary');
libraryEditElements.forEach(function (btn) {
btn.addEventListener('click', function () {
const card = dom.parentWithClass(btn, 'card');
const index = parseInt(card.getAttribute('data-index'), 10);
const virtualFolder = virtualFolders[index];
if (virtualFolder.ItemId) {
editVirtualFolder(page, virtualFolder);
}
});
});
loading.hide();
}
function editImages(page, virtualFolder) {
import('components/imageeditor/imageeditor').then((imageEditor) => {
imageEditor.show({
itemId: virtualFolder.ItemId,
serverId: ApiClient.serverId()
}).then(function () {
reloadLibrary(page);
});
});
}
function getLink(text, url) {
return globalize.translate(text, '<a is="emby-linkbutton" class="button-link" href="' + url + '" target="_blank" data-autohide="true">', '</a>');
}
function getCollectionTypeOptions() {
return [{
name: '',
value: ''
}, {
name: globalize.translate('Movies'),
value: 'movies',
message: getLink('MovieLibraryHelp', 'https://jellyfin.org/docs/general/server/media/movies')
}, {
name: globalize.translate('TabMusic'),
value: 'music',
message: getLink('MusicLibraryHelp', 'https://jellyfin.org/docs/general/server/media/music')
}, {
name: globalize.translate('Shows'),
value: 'tvshows',
message: getLink('TvLibraryHelp', 'https://jellyfin.org/docs/general/server/media/shows')
}, {
name: globalize.translate('Books'),
value: 'books',
message: getLink('BookLibraryHelp', 'https://jellyfin.org/docs/general/server/media/books')
}, {
name: globalize.translate('HomeVideosPhotos'),
value: 'homevideos'
}, {
name: globalize.translate('MusicVideos'),
value: 'musicvideos'
}, {
name: globalize.translate('MixedMoviesShows'),
value: 'mixed',
message: globalize.translate('MessageUnsetContentHelp')
}];
}
function getVirtualFolderHtml(page, virtualFolder, index) {
let html = '';
const elementId = virtualFolder.elementId ? `id="${virtualFolder.elementId}" ` : '';
html += '<div ' + elementId + 'class="card backdropCard scalableCard backdropCard-scalable" style="min-width:33.3%;" data-index="' + index + '" data-id="' + virtualFolder.ItemId + '">';
html += '<div class="cardBox visualCardBox">';
html += '<div class="cardScalable visualCardBox-cardScalable">';
html += '<div class="cardPadder cardPadder-backdrop"></div>';
html += '<div class="cardContent">';
let imgUrl = '';
if (virtualFolder.PrimaryImageItemId) {
imgUrl = ApiClient.getScaledImageUrl(virtualFolder.PrimaryImageItemId, {
maxWidth: Math.round(dom.getScreenWidth() * 0.40),
type: 'Primary'
});
}
let hasCardImageContainer;
if (imgUrl) {
html += `<div class="cardImageContainer editLibrary ${imgUrl ? '' : getDefaultBackgroundClass()}" style="cursor:pointer">`;
html += `<img src="${imgUrl}" style="width:100%" />`;
hasCardImageContainer = true;
} else if (!virtualFolder.showNameWithIcon) {
html += `<div class="cardImageContainer editLibrary ${getDefaultBackgroundClass()}" style="cursor:pointer;">`;
html += '<span class="cardImageIcon material-icons ' + (virtualFolder.icon || imageHelper.getLibraryIcon(virtualFolder.CollectionType)) + '" aria-hidden="true"></span>';
hasCardImageContainer = true;
}
if (hasCardImageContainer) {
html += '<div class="cardIndicators backdropCardIndicators">';
html += '<div is="emby-itemrefreshindicator"' + (virtualFolder.RefreshProgress || virtualFolder.RefreshStatus && virtualFolder.RefreshStatus !== 'Idle' ? '' : ' class="hide"') + ' data-progress="' + (virtualFolder.RefreshProgress || 0) + '" data-status="' + virtualFolder.RefreshStatus + '"></div>';
html += '</div>';
html += '</div>';
}
if (!imgUrl && virtualFolder.showNameWithIcon) {
html += '<h3 class="cardImageContainer addLibrary" style="position:absolute;top:0;left:0;right:0;bottom:0;cursor:pointer;flex-direction:column;">';
html += '<span class="cardImageIcon material-icons ' + (virtualFolder.icon || imageHelper.getLibraryIcon(virtualFolder.CollectionType)) + '" aria-hidden="true"></span>';
if (virtualFolder.showNameWithIcon) {
html += '<div style="margin:1em 0;position:width:100%;">';
html += escapeHtml(virtualFolder.Name);
html += '</div>';
}
html += '</h3>';
}
html += '</div>';
html += '</div>';
html += '<div class="cardFooter visualCardBox-cardFooter">'; // always show menu unless explicitly hidden
if (virtualFolder.showMenu !== false) {
const dirTextAlign = globalize.getIsRTL() ? 'left' : 'right';
html += '<div style="text-align:' + dirTextAlign + '; float:' + dirTextAlign + ';padding-top:5px;">';
html += '<button type="button" is="paper-icon-button-light" class="btnCardMenu autoSize"><span class="material-icons more_vert" aria-hidden="true"></span></button>';
html += '</div>';
}
html += "<div class='cardText'>";
if (virtualFolder.showNameWithIcon) {
html += '&nbsp;';
} else {
html += escapeHtml(virtualFolder.Name);
}
html += '</div>';
let typeName = getCollectionTypeOptions().filter(function (t) {
return t.value == virtualFolder.CollectionType;
})[0];
typeName = typeName ? typeName.name : globalize.translate('Other');
html += "<div class='cardText cardText-secondary'>";
if (virtualFolder.showType === false) {
html += '&nbsp;';
} else {
html += typeName;
}
html += '</div>';
if (virtualFolder.showLocations === false) {
html += "<div class='cardText cardText-secondary'>";
html += '&nbsp;';
html += '</div>';
} else if (virtualFolder.Locations.length && virtualFolder.Locations.length === 1) {
html += "<div class='cardText cardText-secondary' dir='ltr' style='text-align:left;'>";
html += virtualFolder.Locations[0];
html += '</div>';
} else {
html += "<div class='cardText cardText-secondary'>";
html += globalize.translate('NumLocationsValue', virtualFolder.Locations.length);
html += '</div>';
}
html += '</div>';
html += '</div>';
html += '</div>';
return html;
}
window.WizardLibraryPage = {
next: function () {
Dashboard.navigate('wizard/settings');
}
};
pageClassOn('pageshow', 'mediaLibraryPage', function () {
reloadLibrary(this);
});
pageIdOn('pageshow', 'mediaLibraryPage', function () {
const page = this;
taskButton({
mode: 'on',
progressElem: page.querySelector('.refreshProgress'),
taskKey: 'RefreshLibrary',
button: page.querySelector('.btnRefresh')
});
});
pageIdOn('pagebeforehide', 'mediaLibraryPage', function () {
const page = this;
taskButton({
mode: 'off',
progressElem: page.querySelector('.refreshProgress'),
taskKey: 'RefreshLibrary',
button: page.querySelector('.btnRefresh')
});
});
@@ -0,0 +1,28 @@
<div id="wizardSettingsPage" data-role="page" class="page standalonePage wizardPage">
<div class="padded-left padded-right padded-top">
<div class="ui-corner-all ui-shadow wizardContent">
<form class="wizardSettingsForm">
<h1>${HeaderConfigureRemoteAccess}</h1>
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input type="checkbox" is="emby-checkbox" id="chkRemoteAccess" checked />
<span>${AllowRemoteAccess}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${AllowRemoteAccessHelp}</div>
</div>
<br />
<div class="wizardNavigation">
<button is="emby-button" type="button" class="raised button-cancel" onclick="history.back();">
<span class="material-icons arrow_back" aria-hidden="true"></span>
<span>${Previous}</span>
</button>
<button is="emby-button" type="submit" class="raised button-submit">
<span>${Next}</span>
<span class="material-icons arrow_forward" aria-hidden="true"></span>
</button>
</div>
</form>
</div>
</div>
</div>
@@ -0,0 +1,43 @@
import loading from 'components/loading/loading';
import 'elements/emby-checkbox/emby-checkbox';
import 'elements/emby-button/emby-button';
import 'elements/emby-select/emby-select';
import Dashboard from 'utils/dashboard';
function save(page) {
loading.show();
const apiClient = ApiClient;
const config = {
EnableRemoteAccess: page.querySelector('#chkRemoteAccess').checked
};
apiClient.ajax({
type: 'POST',
data: JSON.stringify(config),
url: apiClient.getUrl('Startup/RemoteAccess'),
contentType: 'application/json'
}).then(function () {
loading.hide();
navigateToNextPage();
});
}
function navigateToNextPage() {
Dashboard.navigate('wizard/finish');
}
function onSubmit(e) {
save(this);
e.preventDefault();
return false;
}
export default function (view) {
view.querySelector('.wizardSettingsForm').addEventListener('submit', onSubmit);
view.addEventListener('viewshow', function () {
document.querySelector('.skinHeader').classList.add('noHomeButtonHeader');
});
view.addEventListener('viewhide', function () {
document.querySelector('.skinHeader').classList.remove('noHomeButtonHeader');
});
}
@@ -0,0 +1,31 @@
<div id="wizardSettingsPage" data-role="page" class="page standalonePage wizardPage">
<div class="padded-left padded-right padded-top">
<div class="ui-corner-all ui-shadow wizardContent">
<form class="wizardSettingsForm">
<h1>${HeaderPreferredMetadataLanguage}</h1>
<p style="margin:1.5em 0;">${DefaultMetadataLangaugeDescription}</p>
<div class="selectContainer">
<select is="emby-select" id="selectLanguage" required="required" label="${LabelLanguage}"></select>
</div>
<div class="selectContainer">
<select is="emby-select" id="selectCountry" required="required" label="${LabelCountry}"></select>
</div>
<br />
<div class="wizardNavigation">
<button is="emby-button" type="button" class="raised button-cancel" onclick="history.back();">
<span class="material-icons arrow_back" aria-hidden="true"></span>
<span>${Previous}</span>
</button>
<button is="emby-button" type="submit" class="raised button-submit">
<span>${Next}</span>
<span class="material-icons arrow_forward" aria-hidden="true"></span>
</button>
</div>
</form>
</div>
</div>
</div>
@@ -0,0 +1,87 @@
import loading from 'components/loading/loading';
import 'elements/emby-checkbox/emby-checkbox';
import 'elements/emby-button/emby-button';
import 'elements/emby-select/emby-select';
import Dashboard from 'utils/dashboard';
function save(page) {
loading.show();
const apiClient = ApiClient;
apiClient.getJSON(apiClient.getUrl('Startup/Configuration')).then(function (config) {
config.PreferredMetadataLanguage = page.querySelector('#selectLanguage').value;
config.MetadataCountryCode = page.querySelector('#selectCountry').value;
apiClient.ajax({
type: 'POST',
data: JSON.stringify(config),
url: apiClient.getUrl('Startup/Configuration'),
contentType: 'application/json'
}).then(function () {
loading.hide();
navigateToNextPage();
});
});
}
function populateLanguages(select, languages) {
let html = '';
html += "<option value=''></option>";
for (let i = 0, length = languages.length; i < length; i++) {
const culture = languages[i];
html += "<option value='" + culture.TwoLetterISOLanguageName + "'>" + culture.DisplayName + '</option>';
}
select.innerHTML = html;
}
function populateCountries(select, allCountries) {
let html = '';
html += "<option value=''></option>";
for (let i = 0, length = allCountries.length; i < length; i++) {
const culture = allCountries[i];
html += "<option value='" + culture.TwoLetterISORegionName + "'>" + culture.DisplayName + '</option>';
}
select.innerHTML = html;
}
function reloadData(page, config, cultures, countries) {
populateLanguages(page.querySelector('#selectLanguage'), cultures);
populateCountries(page.querySelector('#selectCountry'), countries);
page.querySelector('#selectLanguage').value = config.PreferredMetadataLanguage;
page.querySelector('#selectCountry').value = config.MetadataCountryCode;
loading.hide();
}
function reload(page) {
loading.show();
const apiClient = ApiClient;
const promise1 = apiClient.getJSON(apiClient.getUrl('Startup/Configuration'));
const promise2 = apiClient.getCultures();
const promise3 = apiClient.getCountries();
Promise.all([promise1, promise2, promise3]).then(function (responses) {
reloadData(page, responses[0], responses[1], responses[2]);
});
}
function navigateToNextPage() {
Dashboard.navigate('wizard/remoteaccess');
}
function onSubmit(e) {
save(this);
e.preventDefault();
return false;
}
export default function (view) {
view.querySelector('.wizardSettingsForm').addEventListener('submit', onSubmit);
view.addEventListener('viewshow', function () {
document.querySelector('.skinHeader').classList.add('noHomeButtonHeader');
reload(this);
});
view.addEventListener('viewhide', function () {
document.querySelector('.skinHeader').classList.remove('noHomeButtonHeader');
});
}
@@ -0,0 +1,29 @@
<div id="wizardStartPage" data-role="page" class="page standalonePage wizardPage">
<div class="padded-left padded-right padded-top">
<div class="ui-corner-all ui-shadow wizardContent" style="position:relative;">
<form class="wizardStartForm">
<div>
<h1 style="float:left;">${WelcomeToProject}</h1>
<a is="emby-linkbutton" rel="noopener noreferrer" href="https://jellyfin.org/docs/general/quick-start" target="_blank" class="raised raised-alt" style="float:right;margin-top:20px;">
<span>${ButtonQuickStartGuide}</span>
</a>
</div>
<br style="clear:both;" />
<p>${ThisWizardWillGuideYou}</p>
<br />
<div class="selectContainer">
<select is="emby-select" id="selectLocalizationLanguage" label="${LabelPreferredDisplayLanguage}"></select>
</div>
<br />
<div class="wizardNavigation" style="text-align:right;">
<button is="emby-button" type="submit" class="raised button-submit">
<span>${Next}</span>
<span class="material-icons arrow_forward" aria-hidden="true"></span>
</button>
</div>
</form>
</div>
</div>
</div>
@@ -0,0 +1,53 @@
import loading from 'components/loading/loading';
import 'elements/emby-button/emby-button';
import 'elements/emby-select/emby-select';
import Dashboard from 'utils/dashboard';
import dom from 'scripts/dom';
function loadPage(page, config, languageOptions) {
const elem = page.querySelector('#selectLocalizationLanguage');
elem.innerHTML = languageOptions.map(function (l) {
return '<option value="' + l.Value + '">' + l.Name + '</option>';
}).join('');
elem.value = config.UICulture;
loading.hide();
}
function save(page) {
loading.show();
const apiClient = ApiClient;
apiClient.getJSON(apiClient.getUrl('Startup/Configuration')).then(function (config) {
config.UICulture = page.querySelector('#selectLocalizationLanguage').value;
apiClient.ajax({
type: 'POST',
data: JSON.stringify(config),
url: apiClient.getUrl('Startup/Configuration'),
contentType: 'application/json'
}).then(function () {
Dashboard.navigate('wizard/user');
});
});
}
function onSubmit(e) {
e.preventDefault();
save(dom.parentWithClass(this, 'page'));
}
export default function (view) {
view.querySelector('.wizardStartForm').addEventListener('submit', onSubmit);
view.addEventListener('viewshow', function () {
document.querySelector('.skinHeader').classList.add('noHomeButtonHeader');
loading.show();
const page = this;
const apiClient = ApiClient;
const promise1 = apiClient.getJSON(apiClient.getUrl('Startup/Configuration'));
const promise2 = apiClient.getJSON(apiClient.getUrl('Localization/Options'));
Promise.all([promise1, promise2]).then(function (responses) {
loadPage(page, responses[0], responses[1]);
});
});
view.addEventListener('viewhide', function () {
document.querySelector('.skinHeader').classList.remove('noHomeButtonHeader');
});
}
@@ -0,0 +1,36 @@
<div id="wizardUserPage" data-role="page" class="page standalonePage wizardPage">
<div class="padded-left padded-right padded-top">
<div class="ui-corner-all ui-shadow wizardContent">
<form class="wizardUserForm">
<div class="verticalSection">
<h1 class="sectionTitle">${TellUsAboutYourself}</h1>
<p style="margin-top:2em;">${UserProfilesIntro}</p>
<br />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtUsername" label="${LabelUsername}" required="required" />
<div class="fieldDescription">${SelectAdminUsername}</div>
</div>
<div class="inputContainer">
<input is="emby-input" id="txtManualPassword" type="password" label="${LabelPassword}" required="required" />
<div class="fieldDescription">${PasswordRequiredForAdmin}</div>
</div>
<div class="inputContainer">
<input is="emby-input" id="txtPasswordConfirm" type="password" label="${LabelPasswordConfirm}" required="required" />
</div>
<p>${MoreUsersCanBeAddedLater}</p>
</div>
<div class="wizardNavigation">
<button is="emby-button" type="button" class="raised button-cancel" onclick="history.back();">
<span class="material-icons arrow_back" aria-hidden="true"></span>
<span>${Previous}</span>
</button>
<button is="emby-button" type="submit" class="raised button-submit">
<span>${Next}</span>
<span class="material-icons arrow_forward" aria-hidden="true"></span>
</button>
</div>
</form>
</div>
</div>
</div>
+83
View File
@@ -0,0 +1,83 @@
import loading from 'components/loading/loading';
import globalize from 'lib/globalize';
import 'styles/dashboard.scss';
import 'elements/emby-input/emby-input';
import 'elements/emby-button/emby-button';
import Dashboard from 'utils/dashboard';
import toast from 'components/toast/toast';
function getApiClient() {
return ApiClient;
}
function nextWizardPage() {
Dashboard.navigate('wizard/library')
.catch(err => {
console.error('[Wizard > User] error navigating to library setup', err);
});
}
function onUpdateUserComplete(result) {
console.debug('[Wizard > User] user update complete:', result);
loading.hide();
nextWizardPage();
}
async function onUpdateUserError(result) {
const message = await result.text();
console.warn('[Wizard > User] user update failed:', message);
toast(globalize.translate('ErrorDefault'));
loading.hide();
}
function submit(form) {
loading.show();
const apiClient = getApiClient();
apiClient
.ajax({
type: 'POST',
data: JSON.stringify({
Name: form.querySelector('#txtUsername').value.trim(),
Password: form.querySelector('#txtManualPassword').value
}),
url: apiClient.getUrl('Startup/User'),
contentType: 'application/json'
})
.then(onUpdateUserComplete)
.catch(onUpdateUserError);
}
function onSubmit(e) {
const form = this;
if (form.querySelector('#txtManualPassword').value != form.querySelector('#txtPasswordConfirm').value) {
toast(globalize.translate('PasswordMatchError'));
} else {
submit(form);
}
e.preventDefault();
return false;
}
function onViewShow() {
loading.show();
const page = this;
const apiClient = getApiClient();
apiClient.getJSON(apiClient.getUrl('Startup/User')).then(function (user) {
page.querySelector('#txtUsername').value = user.Name || '';
page.querySelector('#txtManualPassword').value = user.Password || '';
loading.hide();
});
}
export default function (view) {
view.querySelector('.wizardUserForm').addEventListener('submit', onSubmit);
view.addEventListener('viewshow', function () {
document.querySelector('.skinHeader').classList.add('noHomeButtonHeader');
});
view.addEventListener('viewhide', function () {
document.querySelector('.skinHeader').classList.remove('noHomeButtonHeader');
});
view.addEventListener('viewshow', onViewShow);
}