mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
convert NewUserPage to react
This commit is contained in:
parent
42a593d08a
commit
ccecc4a4b1
10 changed files with 439 additions and 190 deletions
|
@ -0,0 +1,32 @@
|
||||||
|
import React, { FunctionComponent } from 'react';
|
||||||
|
import globalize from '../../../../scripts/globalize';
|
||||||
|
|
||||||
|
const createButtonElement = ({ type, className, title }) => ({
|
||||||
|
__html: `<button
|
||||||
|
is="emby-button"
|
||||||
|
type="${type}"
|
||||||
|
class="${className}"
|
||||||
|
>
|
||||||
|
<span>${title}</span>
|
||||||
|
</button>`
|
||||||
|
});
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
type?: string;
|
||||||
|
className?: string;
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const ButtonElement: FunctionComponent<IProps> = ({ type, className, title }: IProps) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
dangerouslySetInnerHTML={createButtonElement({
|
||||||
|
type: type,
|
||||||
|
className: className,
|
||||||
|
title: globalize.translate(title)
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ButtonElement;
|
|
@ -0,0 +1,33 @@
|
||||||
|
import React, { FunctionComponent } from 'react';
|
||||||
|
import globalize from '../../../../scripts/globalize';
|
||||||
|
|
||||||
|
const createCheckBoxElement = ({ type, className, title }) => ({
|
||||||
|
__html: `<label>
|
||||||
|
<input
|
||||||
|
is="emby-checkbox"
|
||||||
|
type="${type}"
|
||||||
|
class="${className}"
|
||||||
|
/>
|
||||||
|
<span>${title}</span>
|
||||||
|
</label>`
|
||||||
|
});
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
type?: string;
|
||||||
|
className?: string;
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const CheckBoxElement: FunctionComponent<IProps> = ({ type, className, title }: IProps) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
dangerouslySetInnerHTML={createCheckBoxElement({
|
||||||
|
type: type,
|
||||||
|
className: className,
|
||||||
|
title: globalize.translate(title)
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CheckBoxElement;
|
|
@ -0,0 +1,34 @@
|
||||||
|
import React, { FunctionComponent } from 'react';
|
||||||
|
import globalize from '../../../../scripts/globalize';
|
||||||
|
|
||||||
|
const createInputElement = ({ type, id, label, options }) => ({
|
||||||
|
__html: `<input
|
||||||
|
is="emby-input"
|
||||||
|
type="${type}"
|
||||||
|
id="${id}"
|
||||||
|
label="${label}"
|
||||||
|
${options}
|
||||||
|
/>`
|
||||||
|
});
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
type?: string;
|
||||||
|
id?: string;
|
||||||
|
label?: string;
|
||||||
|
options?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const InputElement: FunctionComponent<IProps> = ({ type, id, label, ...rest }: IProps) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
dangerouslySetInnerHTML={createInputElement({
|
||||||
|
type: type,
|
||||||
|
id: id,
|
||||||
|
label: globalize.translate(label),
|
||||||
|
options: rest.options ? rest.options : ''
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InputElement;
|
|
@ -0,0 +1,34 @@
|
||||||
|
import React, { FunctionComponent } from 'react';
|
||||||
|
import globalize from '../../../../scripts/globalize';
|
||||||
|
|
||||||
|
const createLinkElement = ({ className, title, href }) => ({
|
||||||
|
__html: `<a
|
||||||
|
is="emby-linkbutton"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="${className}"
|
||||||
|
target="_blank"
|
||||||
|
href="${href}"
|
||||||
|
>
|
||||||
|
${title}
|
||||||
|
</a>`
|
||||||
|
});
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
title?: string;
|
||||||
|
className?: string;
|
||||||
|
url?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const SectionTitleLinkElement: FunctionComponent<IProps> = ({ className, title, url }: IProps) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
dangerouslySetInnerHTML={createLinkElement({
|
||||||
|
className: className,
|
||||||
|
title: globalize.translate(title),
|
||||||
|
href: url
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SectionTitleLinkElement;
|
|
@ -0,0 +1,32 @@
|
||||||
|
import React, { FunctionComponent } from 'react';
|
||||||
|
|
||||||
|
const createCheckBoxElement = ({Name, Id}) => ({
|
||||||
|
__html: `<label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
is="emby-checkbox"
|
||||||
|
class="chkChannel"
|
||||||
|
data-id="${Id}"
|
||||||
|
/>
|
||||||
|
<span>${Name}</span>
|
||||||
|
</label>`
|
||||||
|
});
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
Name?: string;
|
||||||
|
Id?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ChannelAccess: FunctionComponent<IProps> = ({Name, Id}: IProps) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
dangerouslySetInnerHTML={createCheckBoxElement({
|
||||||
|
Name: Name,
|
||||||
|
Id: Id
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ChannelAccess;
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import React, { FunctionComponent } from 'react';
|
||||||
|
|
||||||
|
const createCheckBoxElement = ({Name, Id}) => ({
|
||||||
|
__html: `<label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
is="emby-checkbox"
|
||||||
|
class="chkFolder"
|
||||||
|
data-id="${Id}"
|
||||||
|
/>
|
||||||
|
<span>${Name}</span>
|
||||||
|
</label>`
|
||||||
|
});
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
Name?: string;
|
||||||
|
Id?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FolderAccess: FunctionComponent<IProps> = ({Name, Id}: IProps) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
dangerouslySetInnerHTML={createCheckBoxElement({
|
||||||
|
Name: Name,
|
||||||
|
Id: Id
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FolderAccess;
|
||||||
|
|
241
src/components/pages/NewUserPage.tsx
Normal file
241
src/components/pages/NewUserPage.tsx
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
import React, { FunctionComponent, useEffect, useState, useRef } from 'react';
|
||||||
|
|
||||||
|
import Dashboard from '../../scripts/clientUtils';
|
||||||
|
import globalize from '../../scripts/globalize';
|
||||||
|
import loading from '../loading/loading';
|
||||||
|
import toast from '../toast/toast';
|
||||||
|
|
||||||
|
import SectionTitleLinkElement from '../DashboardComponent/users/ElementComponent/SectionTitleLinkElement';
|
||||||
|
import InputElement from '../DashboardComponent/users/ElementComponent/InputElement';
|
||||||
|
import CheckBoxElement from '../DashboardComponent/users/ElementComponent/CheckBoxElement';
|
||||||
|
import FolderAccess from '../DashboardComponent/users/NewUserPage/FolderAccess';
|
||||||
|
import ChannelAccess from '../DashboardComponent/users/NewUserPage/ChannelAccess';
|
||||||
|
import ButtonElement from '../DashboardComponent/users/ElementComponent/ButtonElement';
|
||||||
|
|
||||||
|
type userInput = {
|
||||||
|
Name?: string;
|
||||||
|
Password?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NewUserPage: FunctionComponent = () => {
|
||||||
|
const [ channelsResult, setChannelsResult ] = useState([]);
|
||||||
|
const [ mediaFoldersResult, setMediaFoldersResult ] = useState([]);
|
||||||
|
const element = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const loadUser = () => {
|
||||||
|
element.current.querySelector('#txtUsername').value = '';
|
||||||
|
element.current.querySelector('#txtPassword').value = '';
|
||||||
|
loading.show();
|
||||||
|
const promiseFolders = window.ApiClient.getJSON(window.ApiClient.getUrl('Library/MediaFolders', {
|
||||||
|
IsHidden: false
|
||||||
|
}));
|
||||||
|
const promiseChannels = window.ApiClient.getJSON(window.ApiClient.getUrl('Channels'));
|
||||||
|
// eslint-disable-next-line compat/compat
|
||||||
|
Promise.all([promiseFolders, promiseChannels]).then(function (responses) {
|
||||||
|
loadMediaFolders(responses[0].Items);
|
||||||
|
loadChannels(responses[1].Items);
|
||||||
|
loading.hide();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
loadUser();
|
||||||
|
|
||||||
|
const loadMediaFolders = (mediaFolders) => {
|
||||||
|
setMediaFoldersResult(mediaFolders);
|
||||||
|
|
||||||
|
const folderAccess = element?.current?.querySelector('.folderAccess');
|
||||||
|
folderAccess.dispatchEvent(new CustomEvent('create'));
|
||||||
|
|
||||||
|
element.current.querySelector('.chkEnableAllFolders').checked = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadChannels = (channels) => {
|
||||||
|
setChannelsResult(channels);
|
||||||
|
|
||||||
|
const channelAccess = element?.current?.querySelector('.channelAccess');
|
||||||
|
channelAccess.dispatchEvent(new CustomEvent('create'));
|
||||||
|
|
||||||
|
if (channels.length) {
|
||||||
|
element?.current?.querySelector('.channelAccessContainer').classList.remove('hide');
|
||||||
|
} else {
|
||||||
|
element?.current?.querySelector('.channelAccessContainer').classList.add('hide');
|
||||||
|
}
|
||||||
|
|
||||||
|
element.current.querySelector('.chkEnableAllChannels').checked = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveUser = () => {
|
||||||
|
const userInput: userInput = {};
|
||||||
|
userInput.Name = element?.current?.querySelector('#txtUsername').value;
|
||||||
|
userInput.Password = element?.current?.querySelector('#txtPassword').value;
|
||||||
|
window.ApiClient.createUser(userInput).then(function (user) {
|
||||||
|
user.Policy.EnableAllFolders = element?.current?.querySelector('.chkEnableAllFolders').checked;
|
||||||
|
user.Policy.EnabledFolders = [];
|
||||||
|
|
||||||
|
if (!user.Policy.EnableAllFolders) {
|
||||||
|
user.Policy.EnabledFolders = Array.prototype.filter.call(element?.current?.querySelectorAll('.chkFolder'), function (i) {
|
||||||
|
return i.checked;
|
||||||
|
}).map(function (i) {
|
||||||
|
return i.getAttribute('data-id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Policy.EnableAllChannels = element?.current?.querySelector('.chkEnableAllChannels').checked;
|
||||||
|
user.Policy.EnabledChannels = [];
|
||||||
|
|
||||||
|
if (!user.Policy.EnableAllChannels) {
|
||||||
|
user.Policy.EnabledChannels = Array.prototype.filter.call(element?.current?.querySelectorAll('.chkChannel'), function (i) {
|
||||||
|
return i.checked;
|
||||||
|
}).map(function (i) {
|
||||||
|
return i.getAttribute('data-id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () {
|
||||||
|
Dashboard.navigate('useredit.html?userId=' + user.Id);
|
||||||
|
});
|
||||||
|
}, function () {
|
||||||
|
toast(globalize.translate('ErrorDefault'));
|
||||||
|
loading.hide();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = (e) => {
|
||||||
|
loading.show();
|
||||||
|
saveUser();
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chkEnableAllChannels = element?.current?.querySelector('.chkEnableAllChannels');
|
||||||
|
chkEnableAllChannels.addEventListener('change', function (this: HTMLInputElement) {
|
||||||
|
if (this.checked) {
|
||||||
|
element?.current?.querySelector('.channelAccessListContainer').classList.add('hide');
|
||||||
|
} else {
|
||||||
|
element?.current?.querySelector('.channelAccessListContainer').classList.remove('hide');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const chkEnableAllFolders = element?.current?.querySelector('.chkEnableAllFolders');
|
||||||
|
chkEnableAllFolders.addEventListener('change', function (this: HTMLInputElement) {
|
||||||
|
if (this.checked) {
|
||||||
|
element?.current?.querySelector('.folderAccessListContainer').classList.add('hide');
|
||||||
|
} else {
|
||||||
|
element?.current?.querySelector('.folderAccessListContainer').classList.remove('hide');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
element?.current?.querySelector('.newUserProfileForm').addEventListener('submit', onSubmit);
|
||||||
|
|
||||||
|
element?.current?.querySelector('.button-cancel').addEventListener('click', function() {
|
||||||
|
window.history.back();
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={element}>
|
||||||
|
<div className='content-primary'>
|
||||||
|
<div className='verticalSection'>
|
||||||
|
<div className='sectionTitleContainer flex align-items-center'>
|
||||||
|
<h2 className='sectionTitle'>
|
||||||
|
{globalize.translate('ButtonAddUser')}
|
||||||
|
</h2>
|
||||||
|
<SectionTitleLinkElement
|
||||||
|
className='raised button-alt headerHelpButton'
|
||||||
|
title='Help'
|
||||||
|
url='https://docs.jellyfin.org/general/server/users/'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<form className='newUserProfileForm'>
|
||||||
|
<div className='inputContainer'>
|
||||||
|
<InputElement
|
||||||
|
type='text'
|
||||||
|
id='txtUsername'
|
||||||
|
label='LabelName'
|
||||||
|
options={'required'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='inputContainer'>
|
||||||
|
<InputElement
|
||||||
|
type='password'
|
||||||
|
id='txtPassword'
|
||||||
|
label='LabelPassword'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='folderAccessContainer'>
|
||||||
|
<h2>{globalize.translate('HeaderLibraryAccess')}</h2>
|
||||||
|
<CheckBoxElement
|
||||||
|
type='checkbox'
|
||||||
|
className='chkEnableAllFolders'
|
||||||
|
title='OptionEnableAccessToAllLibraries'
|
||||||
|
/>
|
||||||
|
<div className='folderAccessListContainer'>
|
||||||
|
<div className='folderAccess'>
|
||||||
|
<h3 className='checkboxListLabel'>
|
||||||
|
{globalize.translate('HeaderLibraries')}
|
||||||
|
</h3>
|
||||||
|
<div className='checkboxList paperList' style={{padding: '.5em 1em'}}>
|
||||||
|
{mediaFoldersResult.map((folder, index: number)=> (
|
||||||
|
<FolderAccess
|
||||||
|
key={index}
|
||||||
|
Id={folder.Id}
|
||||||
|
Name={folder.Name}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='fieldDescription'>
|
||||||
|
{globalize.translate('LibraryAccessHelp')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='channelAccessContainer verticalSection-extrabottompadding hide'>
|
||||||
|
<h2>{globalize.translate('HeaderChannelAccess')}</h2>
|
||||||
|
<CheckBoxElement
|
||||||
|
type='checkbox'
|
||||||
|
className='chkEnableAllChannels'
|
||||||
|
title='OptionEnableAccessToAllChannels'
|
||||||
|
/>
|
||||||
|
<div className='channelAccessListContainer'>
|
||||||
|
<div className='channelAccess'>
|
||||||
|
<h3 className='checkboxListLabel'>
|
||||||
|
{globalize.translate('Channels')}
|
||||||
|
</h3>
|
||||||
|
<div className='checkboxList paperList' style={{padding: '.5em 1em'}}>
|
||||||
|
{channelsResult.map((folder, index: number)=> (
|
||||||
|
<ChannelAccess
|
||||||
|
key={index}
|
||||||
|
Id={folder.Id}
|
||||||
|
Name={folder.Name}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='fieldDescription'>
|
||||||
|
{globalize.translate('ChannelAccessHelp')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<ButtonElement
|
||||||
|
type='submit'
|
||||||
|
className='raised button-submit block'
|
||||||
|
title='Save'
|
||||||
|
/>
|
||||||
|
<ButtonElement
|
||||||
|
type='button'
|
||||||
|
className='raised button-cancel block btnCancel'
|
||||||
|
title='ButtonCancel'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NewUserPage;
|
|
@ -1,62 +1,3 @@
|
||||||
<div id="newUserPage" data-role="page" class="page type-interior">
|
<div id="newUserPage" data-role="page" class="page type-interior">
|
||||||
<div>
|
|
||||||
<div class="content-primary">
|
|
||||||
<form class="newUserProfileForm">
|
|
||||||
<div class="verticalSection">
|
|
||||||
<div class="sectionTitleContainer flex align-items-center">
|
|
||||||
<h2 class="sectionTitle">${ButtonAddUser}</h2>
|
|
||||||
<a is="emby-linkbutton" rel="noopener noreferrer" class="raised button-alt headerHelpButton" target="_blank" href="https://docs.jellyfin.org/general/server/users/">${Help}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="inputContainer">
|
|
||||||
<input is="emby-input" id="txtUsername" required type="text" label="${LabelName}" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="inputContainer">
|
|
||||||
<input is="emby-input" id="txtPassword" type="password" label="${LabelPassword}" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="folderAccessContainer verticalSection">
|
|
||||||
<h2 class="sectionTitle">${HeaderLibraryAccess}</h2>
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" is="emby-checkbox" id="chkEnableAllFolders" />
|
|
||||||
<span>${OptionEnableAccessToAllLibraries}</span>
|
|
||||||
</label>
|
|
||||||
<div class="fieldDescription checkboxFieldDescription">${LibraryAccessHelp}</div>
|
|
||||||
</div>
|
|
||||||
<div class="folderAccessListContainer">
|
|
||||||
<div class="folderAccess">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="channelAccessContainer verticalSection verticalSection-extrabottompadding" style="display:none;">
|
|
||||||
<h2 class="sectionTitle">${HeaderChannelAccess}</h2>
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" is="emby-checkbox" id="chkEnableAllChannels" />
|
|
||||||
<span>${OptionEnableAccessToAllChannels}</span>
|
|
||||||
</label>
|
|
||||||
<div class="fieldDescription checkboxFieldDescription">${ChannelAccessHelp}</div>
|
|
||||||
</div>
|
|
||||||
<div class="channelAccessListContainer">
|
|
||||||
<div class="channelAccess">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button is="emby-button" type="submit" class="raised button-submit block">
|
|
||||||
<span>${Save}</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button is="emby-button" type="button" class="raised button-cancel block btnCancel" onclick="history.back();">
|
|
||||||
<span>${ButtonCancel}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,130 +0,0 @@
|
||||||
import 'jquery';
|
|
||||||
import loading from '../../../components/loading/loading';
|
|
||||||
import globalize from '../../../scripts/globalize';
|
|
||||||
import '../../../elements/emby-checkbox/emby-checkbox';
|
|
||||||
import Dashboard from '../../../scripts/clientUtils';
|
|
||||||
import toast from '../../../components/toast/toast';
|
|
||||||
|
|
||||||
/* eslint-disable indent */
|
|
||||||
|
|
||||||
function loadMediaFolders(page, mediaFolders) {
|
|
||||||
let html = '';
|
|
||||||
html += '<h3 class="checkboxListLabel">' + globalize.translate('HeaderLibraries') + '</h3>';
|
|
||||||
html += '<div class="checkboxList paperList" style="padding:.5em 1em;">';
|
|
||||||
|
|
||||||
for (let i = 0; i < mediaFolders.length; i++) {
|
|
||||||
const folder = mediaFolders[i];
|
|
||||||
html += '<label><input type="checkbox" is="emby-checkbox" class="chkFolder" data-id="' + folder.Id + '"/><span>' + folder.Name + '</span></label>';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '</div>';
|
|
||||||
$('.folderAccess', page).html(html).trigger('create');
|
|
||||||
$('#chkEnableAllFolders', page).prop('checked', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadChannels(page, channels) {
|
|
||||||
let html = '';
|
|
||||||
html += '<h3 class="checkboxListLabel">' + globalize.translate('Channels') + '</h3>';
|
|
||||||
html += '<div class="checkboxList paperList" style="padding:.5em 1em;">';
|
|
||||||
|
|
||||||
for (let i = 0; i < channels.length; i++) {
|
|
||||||
const folder = channels[i];
|
|
||||||
html += '<label><input type="checkbox" is="emby-checkbox" class="chkChannel" data-id="' + folder.Id + '"/><span>' + folder.Name + '</span></label>';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '</div>';
|
|
||||||
$('.channelAccess', page).show().html(html).trigger('create');
|
|
||||||
|
|
||||||
if (channels.length) {
|
|
||||||
$('.channelAccessContainer', page).show();
|
|
||||||
} else {
|
|
||||||
$('.channelAccessContainer', page).hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#chkEnableAllChannels', page).prop('checked', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadUser(page) {
|
|
||||||
$('#txtUsername', page).val('');
|
|
||||||
$('#txtPassword', page).val('');
|
|
||||||
loading.show();
|
|
||||||
const promiseFolders = ApiClient.getJSON(ApiClient.getUrl('Library/MediaFolders', {
|
|
||||||
IsHidden: false
|
|
||||||
}));
|
|
||||||
const promiseChannels = ApiClient.getJSON(ApiClient.getUrl('Channels'));
|
|
||||||
Promise.all([promiseFolders, promiseChannels]).then(function (responses) {
|
|
||||||
loadMediaFolders(page, responses[0].Items);
|
|
||||||
loadChannels(page, responses[1].Items);
|
|
||||||
loading.hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveUser(page) {
|
|
||||||
const user = {};
|
|
||||||
user.Name = $('#txtUsername', page).val();
|
|
||||||
user.Password = $('#txtPassword', page).val();
|
|
||||||
ApiClient.createUser(user).then(function (user) {
|
|
||||||
user.Policy.EnableAllFolders = $('#chkEnableAllFolders', page).is(':checked');
|
|
||||||
user.Policy.EnabledFolders = [];
|
|
||||||
|
|
||||||
if (!user.Policy.EnableAllFolders) {
|
|
||||||
user.Policy.EnabledFolders = $('.chkFolder', page).get().filter(function (i) {
|
|
||||||
return i.checked;
|
|
||||||
}).map(function (i) {
|
|
||||||
return i.getAttribute('data-id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
user.Policy.EnableAllChannels = $('#chkEnableAllChannels', page).is(':checked');
|
|
||||||
user.Policy.EnabledChannels = [];
|
|
||||||
|
|
||||||
if (!user.Policy.EnableAllChannels) {
|
|
||||||
user.Policy.EnabledChannels = $('.chkChannel', page).get().filter(function (i) {
|
|
||||||
return i.checked;
|
|
||||||
}).map(function (i) {
|
|
||||||
return i.getAttribute('data-id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () {
|
|
||||||
Dashboard.navigate('useredit.html?userId=' + user.Id);
|
|
||||||
});
|
|
||||||
}, function () {
|
|
||||||
toast(globalize.translate('ErrorDefault'));
|
|
||||||
loading.hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSubmit() {
|
|
||||||
const page = $(this).parents('.page')[0];
|
|
||||||
loading.show();
|
|
||||||
saveUser(page);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadData(page) {
|
|
||||||
loadUser(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).on('pageinit', '#newUserPage', function () {
|
|
||||||
const page = this;
|
|
||||||
$('#chkEnableAllChannels', page).on('change', function () {
|
|
||||||
if (this.checked) {
|
|
||||||
$('.channelAccessListContainer', page).hide();
|
|
||||||
} else {
|
|
||||||
$('.channelAccessListContainer', page).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$('#chkEnableAllFolders', page).on('change', function () {
|
|
||||||
if (this.checked) {
|
|
||||||
$('.folderAccessListContainer', page).hide();
|
|
||||||
} else {
|
|
||||||
$('.folderAccessListContainer', page).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$('.newUserProfileForm').off('submit', onSubmit).on('submit', onSubmit);
|
|
||||||
}).on('pageshow', '#newUserPage', function () {
|
|
||||||
loadData(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
/* eslint-enable indent */
|
|
|
@ -456,7 +456,7 @@ import { appRouter } from '../components/appRouter';
|
||||||
path: 'dashboard/users/usernew.html',
|
path: 'dashboard/users/usernew.html',
|
||||||
autoFocus: false,
|
autoFocus: false,
|
||||||
roles: 'admin',
|
roles: 'admin',
|
||||||
controller: 'dashboard/users/usernew'
|
pageComponent: 'NewUserPage'
|
||||||
});
|
});
|
||||||
|
|
||||||
defineRoute({
|
defineRoute({
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue