PDF rausgenommen

This commit is contained in:
aschwarz
2023-01-23 11:03:31 +01:00
parent 82d562a322
commit a6523903eb
28078 changed files with 4247552 additions and 2 deletions

View File

@ -0,0 +1,218 @@
<div class="userPermissionsEdit" ng-class="{ loading: $ctrl.isLoadingAccess }">
<div class="row" ng-if="!$ctrl.hasAccessToAtLeastOneSite">
<div piwik-notification context="warning" type="persistent" noclear="true">
<strong>{{:: 'General_Warning'|translate }}:</strong>
{{:: 'UsersManager_NoAccessWarning'|translate }}
</div>
</div>
<div class="row to-all-websites">
<div class="col s12">
<div>
<span>{{ 'UsersManager_GiveAccessToAll'|translate }}:</span>
<div
id="all-sites-access-select"
piwik-field
uicontrol="select"
ng-model="$ctrl.allWebsitesAccssLevelSet"
options="$ctrl.accessLevels"
full-width="true"
></div>
<a href="" class="btn" ng-class="{ disabled: $ctrl.isGivingAccessToAllSites }" ng-click="$ctrl.showChangeAccessAllSitesModal()">
{{:: 'General_Apply'|translate }}
</a>
</div>
<p>&nbsp;</p>
<p>{{ 'UsersManager_OrManageIndividually'|translate }}:</p>
</div>
</div>
<div class="filters row">
<div class="col s12 m12 l8">
<div class="input-field bulk-actions">
<a
class='dropdown-trigger btn'
href=''
data-activates='user-permissions-edit-bulk-actions'
piwik-dropdown-menu
ng-class="{ disabled: $ctrl.isBulkActionsDisabled }"
>
{{:: 'UsersManager_BulkActions'|translate }}
</a>
<ul id='user-permissions-edit-bulk-actions' class='dropdown-content'>
<li>
<a class='dropdown-trigger' data-activates="user-permissions-bulk-set-access" piwik-dropdown-menu>{{:: 'UsersManager_SetPermission'|translate }}</a>
<ul id="user-permissions-bulk-set-access" class="dropdown-content">
<li ng-repeat="access in $ctrl.accessLevels">
<a href="" ng-click="$ctrl.siteAccessToChange = null; $ctrl.roleToChangeTo = access.key; $ctrl.showChangeAccessConfirm();">{{ access.value }}</a>
</li>
</ul>
</li>
<li>
<a href="" ng-click="$ctrl.siteAccessToChange = null; $ctrl.roleToChangeTo = 'noaccess'; $ctrl.showRemoveAccessConfirm();">{{:: 'UsersManager_RemovePermissions'|translate }}</a>
</li>
</ul>
</div>
<div class="input-field site-filter">
<input
type="text"
placeholder="{{:: 'UsersManager_FilterByWebsite'|translate }}"
ng-model="$ctrl.siteNameFilter"
ng-model-options="{debounce: 300}"
ng-change="$ctrl.offset = 0; $ctrl.fetchAccess()"
/>
</div>
<div class="input-field access-filter">
<div
piwik-field
uicontrol="select"
ng-model="$ctrl.accessLevelFilter"
options="$ctrl.filterAccessLevels"
full-width="true"
ng-change="$ctrl.offset = 0; $ctrl.fetchAccess()"
placeholder="{{ 'UsersManager_FilterByAccess'|translate }}"
></div>
</div>
</div>
<div class="col s12 m12 l4 sites-for-permission-pagination-container" ng-if="$ctrl.totalEntries > $ctrl.limit">
<div class="sites-for-permission-pagination">
<a class="prev" ng-class="{ disabled: $ctrl.offset <= 0 }">
<span class="pointer" ng-click="$ctrl.gotoPreviousPage()">« {{:: 'General_Previous'|translate }}</span>
</a>
<span class="counter">
<span>
{{ 'General_Pagination'|translate:$ctrl.getPaginationLowerBound():$ctrl.getPaginationUpperBound():$ctrl.totalEntries }}
</span>
</span>
<a class="next" ng-class="{ disabled: $ctrl.offset + $ctrl.limit >= $ctrl.totalEntries }">
<span class="pointer" ng-click="$ctrl.gotoNextPage()">{{:: 'General_Next'|translate }} »</span>
</a>
</div>
</div>
</div>
<div piwik-notification context="info" type="persistent" noclear="true" ng-if="$ctrl.isRoleHelpToggled" class="roles-help-notification">
<span piwik-translate="UsersManager_RolesHelp">
<a href='https://matomo.org/faq/general/faq_70/' target='_blank' rel='noreferrer noopener'>::</a>::<a href='https://matomo.org/faq/general/faq_69/' target='_blank' rel='noreferrer noopener'>::</a>
</span>
</div>
<div piwik-notification context="info" type="persistent" noclear="true" ng-if="$ctrl.isCapabilitiesHelpToggled" class="capabilities-help-notification">
<span piwik-translate="UsersManager_CapabilitiesHelp">
TODO
</span>
</div>
<table piwik-content-table id="sitesForPermission">
<thead>
<tr>
<th class="select-cell">
<span class="checkbox-container">
<input type="checkbox" id="perm_edit_select_all" ng-model="$ctrl.isAllCheckboxSelected" ng-change="$ctrl.onAllCheckboxChange()" />
<label for="perm_edit_select_all"></label>
</span>
</th>
<th>{{:: 'General_Name'|translate }}</th>
<th class="role_header">
<span>{{:: 'UsersManager_Role'|translate }}</span>
<a href="" class="helpIcon" ng-click="$ctrl.isRoleHelpToggled = !$ctrl.isRoleHelpToggled" ng-class="{ sticky: $ctrl.isRoleHelpToggled }">
<span class="icon-help"></span>
</a>
</th>
<th class="capabilities_header">
<span>{{:: 'UsersManager_Capabilities'|translate }}</span>
<a href="" class="helpIcon" ng-click="$ctrl.isCapabilitiesHelpToggled = !$ctrl.isCapabilitiesHelpToggled" ng-class="{ sticky: $ctrl.isCapabilitiesHelpToggled }">
<span class="icon-help"></span>
</a>
</th>
</tr>
</thead>
<tbody>
<tr class="select-all-row" ng-if="$ctrl.isAllCheckboxSelected && $ctrl.siteAccess.length < $ctrl.totalEntries">
<td colspan="4">
<div ng-if="!$ctrl.areAllResultsSelected">
<span piwik-translate="UsersManager_TheDisplayedWebsitesAreSelected"><strong>{{ $ctrl.siteAccess.length }}</strong></span>
<a href="#" ng-click="$ctrl.areAllResultsSelected = !$ctrl.areAllResultsSelected" piwik-translate="UsersManager_ClickToSelectAll"><strong>{{ $ctrl.totalEntries }}</strong></a>
</div>
<div ng-if="$ctrl.areAllResultsSelected">
<span piwik-translate="UsersManager_AllWebsitesAreSelected"><strong>{{ $ctrl.totalEntries }}</strong></span>
<a href="#" ng-click="$ctrl.areAllResultsSelected = !$ctrl.areAllResultsSelected" piwik-translate="UsersManager_ClickToSelectDisplayedWebsites"><strong>{{ $ctrl.siteAccess.length }}</strong></a>
</div>
</td>
</tr>
<tr ng-repeat="entry in $ctrl.siteAccess">
<td class="select-cell">
<span class="checkbox-container">
<input type="checkbox" ng-attr-id="perm_edit_select_row{{ $index }}" ng-model="$ctrl.selectedRows[$index]" ng-click="$ctrl.onRowSelected()" />
<label ng-attr-for="perm_edit_select_row{{ $index }}"></label>
</span>
</td>
<td>
<span>{{ entry.site_name }}</span>
</td>
<td>
<div
piwik-field
uicontrol="select"
ng-model="entry.role"
options="$ctrl.accessLevels"
ng-change="$ctrl.previousRole = '{{ entry.role }}'; $ctrl.roleToChangeTo = entry.role; $ctrl.siteAccessToChange = entry; $ctrl.showChangeAccessConfirm();"
full-width="true"
class="role-select"
></div>
</td>
<td>
<piwik-capabilities-edit
idsite="entry.idsite"
site-name="entry.site_name"
user-login="$ctrl.userLogin"
user-role="entry.role"
capabilities="entry.capabilities"
on-capabilities-change="$ctrl.fetchAccess()"
>
</piwik-capabilities-edit>
</td>
</tr>
</tbody>
</table>
<div class="delete-access-confirm-modal modal">
<div class="modal-content">
<h3 ng-if="$ctrl.siteAccessToChange" piwik-translate="UsersManager_DeletePermConfirmSingle"><strong>{{ $ctrl.userLogin }}</strong>::<strong>{{ $ctrl.siteAccessToChange.site_name }}</strong></h3>
<p ng-if="!$ctrl.siteAccessToChange" piwik-translate="UsersManager_DeletePermConfirmMultiple"><strong>{{ $ctrl.userLogin }}</strong>::<strong>{{ $ctrl.getAffectedSitesCount() }}</strong></p>
</div>
<div class="modal-footer">
<a href="" class="modal-action modal-close btn" ng-click="$ctrl.changeUserRole()">{{:: 'General_Yes'|translate }}</a>
<a href="" class="modal-action modal-close modal-no" ng-click="$ctrl.siteAccessToChange = null; $ctrl.roleToChangeTo = null;">{{:: 'General_No'|translate }}</a>
</div>
</div>
<div class="change-access-confirm-modal modal">
<div class="modal-content">
<h3 ng-if="$ctrl.siteAccessToChange" piwik-translate="UsersManager_ChangePermToSiteConfirmSingle"><strong>{{ $ctrl.userLogin }}</strong>::<strong>{{ $ctrl.siteAccessToChange.site_name }}</strong>::<strong>{{ $ctrl.getRoleDisplay($ctrl.roleToChangeTo) }}</strong></h3>
<p ng-if="!$ctrl.siteAccessToChange" piwik-translate="UsersManager_ChangePermToSiteConfirmMultiple"><strong>{{ $ctrl.userLogin }}</strong>::<strong>{{ $ctrl.getAffectedSitesCount() }}</strong>::<strong>{{ $ctrl.getRoleDisplay($ctrl.roleToChangeTo) }}</strong></p>
</div>
<div class="modal-footer">
<a href="" class="modal-action modal-close btn" ng-click="$ctrl.changeUserRole()">{{:: 'General_Yes'|translate }}</a>
<a href="" class="modal-action modal-close modal-no" ng-click="$ctrl.siteAccessToChange.role = $ctrl.previousRole; $ctrl.siteAccessToChange = null; $ctrl.roleToChangeTo = null;">{{:: 'General_No'|translate }}</a>
</div>
</div>
<div class="confirm-give-access-all-sites modal">
<div class="modal-content">
<h3 piwik-translate="UsersManager_ChangePermToAllSitesConfirm"><strong>{{ $ctrl.userLogin }}</strong>::<strong>{{ $ctrl.getRoleDisplay($ctrl.allWebsitesAccssLevelSet) }}</strong></h3>
<p>{{ 'UsersManager_ChangePermToAllSitesConfirm2'|translate }}</p>
</div>
<div class="modal-footer">
<a href="" class="modal-action modal-close btn" ng-click="$ctrl.giveAccessToAllSites()">{{:: 'General_Yes'|translate }}</a>
<a href="" class="modal-action modal-close modal-no">{{:: 'General_No'|translate }}</a>
</div>
</div>
</div>

View File

@ -0,0 +1,298 @@
/*!
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
/**
* Usage:
* <piwik-user-permissions-edit>
*/
(function () {
angular.module('piwikApp').component('piwikUserPermissionsEdit', {
templateUrl: 'plugins/UsersManager/angularjs/user-permissions-edit/user-permissions-edit.component.html?cb=' + piwik.cacheBuster,
bindings: {
userLogin: '<',
limit: '<',
onUserHasAccessDetected: '&',
onAccessChange: '&',
accessLevels: '<',
filterAccessLevels: '<'
},
controller: UserPermissionsEditController
});
UserPermissionsEditController.$inject = ['piwikApi', '$element', '$q'];
function UserPermissionsEditController(piwikApi, $element, $q) {
var vm = this;
// search/pagination state
vm.siteAccess = [];
vm.offset = 0;
vm.totalEntries = null;
vm.accessLevelFilter = '';
vm.siteNameFilter = '';
vm.isLoadingAccess = false;
vm.allWebsitesAccssLevelSet = 'view';
// row selection state
vm.isAllCheckboxSelected = false;
vm.selectedRows = {};
vm.isBulkActionsDisabled = true;
vm.areAllResultsSelected = false;
vm.previousRole = null;
// other state
vm.hasAccessToAtLeastOneSite = true;
vm.isRoleHelpToggled = false;
vm.isCapabilitiesHelpToggled = false;
vm.isGivingAccessToAllSites = false;
// intermediate state
vm.roleToChangeTo = null;
vm.siteAccessToChange = null;
vm.$onInit = $onInit;
vm.$onChanges = $onChanges;
vm.onAllCheckboxChange = onAllCheckboxChange;
vm.onRowSelected = onRowSelected;
vm.getPaginationLowerBound = getPaginationLowerBound;
vm.getPaginationUpperBound = getPaginationUpperBound;
vm.fetchAccess = fetchAccess;
vm.gotoPreviousPage = gotoPreviousPage;
vm.gotoNextPage = gotoNextPage;
vm.showRemoveAccessConfirm = showRemoveAccessConfirm;
vm.getSelectedRowsCount = getSelectedRowsCount;
vm.getAffectedSitesCount = getAffectedSitesCount;
vm.changeUserRole = changeUserRole;
vm.showChangeAccessConfirm = showChangeAccessConfirm;
vm.getRoleDisplay = getRoleDisplay;
vm.showAddExistingUserModal = showAddExistingUserModal;
vm.giveAccessToAllSites = giveAccessToAllSites;
vm.showChangeAccessAllSitesModal = showChangeAccessAllSitesModal;
function giveAccessToAllSites() {
vm.isGivingAccessToAllSites = true;
piwikApi.fetch({
method: 'SitesManager.getSitesWithAdminAccess',
}).then(function (allSites) {
var idSites = allSites.map(function (s) { return s.idsite; });
return piwikApi.post({
method: 'UsersManager.setUserAccess'
}, {
userLogin: vm.userLogin,
access: vm.allWebsitesAccssLevelSet,
'idSites[]': idSites,
});
}).then(function () {
return vm.fetchAccess();
})['finally'](function () {
vm.isGivingAccessToAllSites = false;
});
}
function showChangeAccessAllSitesModal() {
$element.find('.confirm-give-access-all-sites').openModal({ dismissible: false });
}
function $onInit() {
vm.limit = vm.limit || 10;
resetSiteToAdd();
fetchAccess();
}
function $onChanges() {
vm.accessLevels = vm.accessLevels.filter(shouldShowAccessLevel);
vm.filterAccessLevels = vm.filterAccessLevels.filter(shouldShowAccessLevel);
if (vm.limit) {
fetchAccess();
}
function shouldShowAccessLevel(entry) {
return entry.key !== 'superuser';
}
}
function fetchAccess() {
vm.isLoadingAccess = true;
piwikApi.fetch({
method: 'UsersManager.getSitesAccessForUser',
limit: vm.limit,
offset: vm.offset,
filter_search: vm.siteNameFilter,
filter_access: vm.accessLevelFilter,
userLogin: vm.userLogin
}, { includeHeaders: true }).then(function (result) {
vm.isLoadingAccess = false;
vm.siteAccess = result.response;
vm.totalEntries = parseInt(result.headers('x-matomo-total-results')) || 0;
vm.hasAccessToAtLeastOneSite = !! result.headers('x-matomo-has-some');
if (vm.onUserHasAccessDetected) {
vm.onUserHasAccessDetected({ hasAccess: vm.hasAccessToAtLeastOneSite });
}
clearSelection();
}).catch(function () {
vm.isLoadingAccess = false;
clearSelection();
});
}
function getAllSitesInSearch() {
return piwikApi.fetch({
method: 'UsersManager.getSitesAccessForUser',
filter_search: vm.siteNameFilter,
filter_access: vm.accessLevelFilter,
userLogin: vm.userLogin,
filter_limit: '-1'
}).then(function (access) {
return access.map(function (a) { return a.idsite; });
});
}
function clearSelection() {
vm.selectedRows = {};
vm.areAllResultsSelected = false;
vm.isBulkActionsDisabled = true;
vm.isAllCheckboxSelected = false;
vm.siteAccessToChange = null;
}
function onAllCheckboxChange() {
if (!vm.isAllCheckboxSelected) {
clearSelection();
} else {
for (var i = 0; i !== vm.siteAccess.length; ++i) {
vm.selectedRows[i] = true;
}
vm.isBulkActionsDisabled = false;
}
}
function onRowSelected() {
var selectedRowKeyCount = getSelectedRowsCount();
vm.isBulkActionsDisabled = selectedRowKeyCount === 0;
vm.isAllCheckboxSelected = selectedRowKeyCount === vm.siteAccess.length;
}
function getPaginationLowerBound() {
return vm.offset + 1;
}
function getPaginationUpperBound() {
return Math.min(vm.offset + vm.limit, vm.totalEntries);
}
function resetSiteToAdd() {
vm.siteToAdd = {
id: null,
name: ''
};
}
function changeUserRole() {
vm.isLoadingAccess = true;
return $q.resolve().then(function () {
if (vm.siteAccessToChange) {
return [vm.siteAccessToChange.idsite];
}
if (vm.areAllResultsSelected) {
return getAllSitesInSearch();
}
return getSelectedSites();
}).then(function (idSites) {
return piwikApi.post({
method: 'UsersManager.setUserAccess'
}, {
userLogin: vm.userLogin,
access: vm.roleToChangeTo,
'idSites[]': idSites
});
}).catch(function () {
// ignore (errors will still be displayed to the user)
}).then(function () {
vm.onAccessChange();
return fetchAccess();
});
}
function getSelectedSites() {
var result = [];
Object.keys(vm.selectedRows).forEach(function (index) {
if (vm.selectedRows[index]
&& vm.siteAccess[index] // safety check
) {
result.push(vm.siteAccess[index].idsite);
}
});
return result;
}
function gotoPreviousPage() {
vm.offset = Math.max(0, vm.offset - vm.limit);
fetchAccess();
}
function gotoNextPage() {
var newOffset = vm.offset + vm.limit;
if (newOffset >= vm.totalEntries) {
return;
}
vm.offset = newOffset;
fetchAccess();
}
function showRemoveAccessConfirm() {
$element.find('.delete-access-confirm-modal').openModal({ dismissible: false });
}
function showChangeAccessConfirm() {
$element.find('.change-access-confirm-modal').openModal({ dismissible: false });
}
function showAddExistingUserModal() {
$element.find('.add-existing-user-modal').openModal({ dismissible: false });
}
function getSelectedRowsCount() {
var selectedRowKeyCount = 0;
Object.keys(vm.selectedRows).forEach(function (key) {
if (vm.selectedRows[key]) {
++selectedRowKeyCount;
}
});
return selectedRowKeyCount;
}
function getAffectedSitesCount() {
if (vm.areAllResultsSelected) {
return vm.totalEntries;
}
return getSelectedRowsCount();
}
function getRoleDisplay(role) {
var result = null;
vm.accessLevels.forEach(function (entry) {
if (entry.key === role) {
result = entry.value;
}
});
return result;
}
}
})();

View File

@ -0,0 +1,232 @@
.userPermissionsEdit {
&.loading {
.sites-for-permission-pagination, table {
opacity: .5;
}
}
.permission-select .select-wrapper {
display: inline-block;
transform: scale(.8);
margin-right: -10px;
margin-left: -10px;
z-index: 999;
input {
margin-bottom: 0;
height: 1.1em;
line-height: 1.1em;
}
.caret {
top: 0;
}
}
.add-site {
float: right;
[piwik-field] {
display:inline-block;
.input-field {
width: 180px;
}
}
[piwik-siteselector] {
display: inline-block;
a.title {
width: 180px;
}
.siteSelector {
position: static !important;
margin-top: 1px;
}
}
.btn-flat:hover {
background: none;
}
}
.filters {
margin-left: -0.75rem;
margin-right: -0.75rem;
display: flex;
flex-direction: row;
justify-content: center;
flex-wrap: wrap;
> div:first-child {
flex: 1;
}
> div > .input-field {
display: inline-block;
vertical-align: top;
width: 180px;
}
.sites-for-permission-pagination {
display: inline-block;
vertical-align: top;
min-height: 2.5rem;
}
.form-group, .input-field, input {
margin: 0;
}
.add-site {
> div {
vertical-align: bottom;
margin-top: .8rem;
}
> a {
padding: 0 1rem 0 0;
}
}
}
.bulk-actions > a.dropdown-trigger {
margin-top: .8rem;
margin-right: 1rem;
}
#sitesForPermission {
margin-left: 0;
margin-right: 0;
width: calc(100%);
font-size: 100%;
td > span {
display:inline-block;
}
.select-cell {
width: 32px;
}
span.checkbox-container {
transform: scale(.8);
margin-top: -4px;
}
.role-select .select-wrapper {
transform: scale(.8) translate(-1.3rem);
margin-top: -0.5rem;
max-width: 160px;
span.caret {
top: 8px;
}
input {
margin-bottom: 0;
height: 2rem;
line-height: 2rem;
}
}
tr.select-all-row > td {
padding: 6px;
text-align: center;
}
.row.form-group {
margin: 0;
.col {
padding: 0;
}
}
tr .input-field {
margin-top: 0;
}
}
table.entityTable tbody tr td {
vertical-align: middle !important;
}
.add-permission {
float: right;
}
.sites-for-permission-pagination-container {
position: relative;
}
.sites-for-permission-pagination {
position: absolute;
bottom: 0;
width: calc(100%);
text-align: center;
a.disabled {
pointer-events: none;
color: #9e9e9e;
}
.counter {
margin-left: 8px;
margin-right: 8px;
}
}
.delete-site-permission {
float: right;
}
.delete-access-confirm-modal, .change-access-confirm-modal, .confirm-give-access-all-sites {
.modal-no {
float: right;
margin-right: 1em;
margin-top: 1em;
}
}
th.role_header, th.capabilities_header {
.helpIcon {
color: #9e9e9e;
font-size: .8rem;
margin-left: .1rem;
text-decoration: none;
&:hover,&.sticky {
opacity: 1;
}
}
}
.to-all-websites {
margin-left: -0.75em;
margin-right: -0.75em;
}
#all-sites-access-select {
display: inline-block;
vertical-align: bottom;
width: 150px;
.form-group {
margin: 0;
}
.input-field {
margin-top: 0;
}
.select-dropdown {
margin-bottom: 0;
}
}
}
.user-permission-toast .notification {
padding-left: 20px;
&::before {
display:none;
}
}