Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,17 @@
fill: $ibexa-color-primary;
}
}

&--disabled {
cursor: default;

&,
&:hover {
.ibexa-icon {
fill: $ibexa-color-dark-400;
}
}
}
}

&__link {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

const { ibexa, Translator } = window;
const { formatShortDateTime } = ibexa.helpers.timezone;
const { getContentTypeData } = ibexa.helpers.contentType;

export default class TableViewItemComponent extends PureComponent {
constructor(props) {
Expand All @@ -20,6 +21,7 @@
this.setPriorityInputRef = this.setPriorityInputRef.bind(this);
this.getLanguageSelectorData = this.getLanguageSelectorData.bind(this);
this.editItem = this.editItem.bind(this);
this.checkIfCanEdit = this.checkIfCanEdit.bind(this);

this._refPriorityInput = null;

Expand Down Expand Up @@ -410,19 +412,44 @@
};
}

checkIfCanEdit(item) {
const editPermissions = item.permissions?.edit;
const contentTypeData = getContentTypeData(item.content._info.contentType.identifier);

if (!editPermissions) {
return false;
}

if (!editPermissions.hasAccess) {
return false;
}

if (!editPermissions.restrictedContentTypeIds.length) {
return editPermissions.hasAccess;
}

return editPermissions.restrictedContentTypeIds.includes(contentTypeData.id.toString());
}

componentDidMount() {
ibexa.helpers.table.parseCheckbox('.c-table-view-item__cell .ibexa-input--checkbox', 'c-table-view-item--active');
}

render() {
const { isSelected, showScrollShadowRight } = this.props;
const { isSelected, showScrollShadowRight, item } = this.props;
const canEdit = this.checkIfCanEdit(item);
const editLabel = Translator.trans(/*@Desc("Edit")*/ 'edit_item_btn.label', {}, 'ibexa_sub_items');
const actionCellClassName = createCssClassNames({
'ibexa-table__cell': true,
'c-table-view-item__cell': true,
'c-table-view-item__cell--actions': true,
'c-table-view-item__cell--shadow-left': showScrollShadowRight,
});
const editBtnClassName = createCssClassNames({
'c-table-view-item__btn': true,
'c-table-view-item__btn--edit': true,
'c-table-view-item__btn--disabled': !canEdit,
});

return (
<tr className="ibexa-table__row c-table-view-item">
Expand All @@ -436,13 +463,14 @@
</td>
{this.renderBasicColumns()}
<td className={actionCellClassName}>
<span
title={editLabel}
data-extra-classes="c-table-view-item__tooltip"
onClick={this.handleEdit}
className="c-table-view-item__btn c-table-view-item__btn--edit"
onClick={canEdit ? this.handleEdit : () => {}}
className={editBtnClassName}
Comment thread
OstafinL marked this conversation as resolved.
tabIndex={-1}
role="button"
>

Check warning on line 473 in src/bundle/ui-dev/src/modules/sub-items/components/table-view/table.view.item.component.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use <input type="button">, <input type="image">, <input type="reset">, <input type="submit">, or <button> instead of the "button" role to ensure accessibility across all devices.

See more on https://sonarcloud.io/project/issues?id=ibexa_admin-ui&issues=AZ-nsMYhFOS-NtQ5Oh0x&open=AZ-nsMYhFOS-NtQ5Oh0x&pullRequest=1978
<div className="c-table-view-item__btn-inner">
<Icon name="edit" extraClasses="ibexa-icon--small-medium" />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export const LOCATION_ENDPOINT = '/api/ibexa/v2/content/locations';
export const CONTENT_OBJECTS_ENDPOINT = '/api/ibexa/v2/content/objects';
export const ENDPOINT_BULK = '/api/ibexa/v2/bulk';
export const ENDPOINT_GRAPHQL = '/graphql';
export const ENDPOINT_LOCATIONS_PERMISSIONS = '/api/ibexa/v2/module/universal-discovery/locations';
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { handleRequestResponse } from '../../common/helpers/request.helper.js';
import { ASCENDING_SORT_ORDER } from '../sub.items.module.js';
import { LOCATION_ENDPOINT, ENDPOINT_GRAPHQL } from './endpoints.js';
import { LOCATION_ENDPOINT, ENDPOINT_GRAPHQL, ENDPOINT_LOCATIONS_PERMISSIONS } from './endpoints.js';

import { getRestInfo } from '@ibexa-admin-ui/src/bundle/Resources/public/js/scripts/helpers/context.helper';
import { getRequestHeaders, getRequestMode } from '@ibexa-admin-ui/src/bundle/Resources/public/js/scripts/helpers/request.helper';
import { showErrorNotification } from '@ibexa-admin-ui/src/bundle/Resources/public/js/scripts/helpers/notification.helper';

const sortClauseGraphQLMap = {
ContentId: '_contentId',
Expand Down Expand Up @@ -141,6 +145,28 @@ export const loadLocation = ({ token, siteaccess }, { locationId = 2, limit = 10
.catch(() => window.ibexa.helpers.notification.showErrorNotification('Cannot load location'));
};

export const loadLocationsPermissions = (locationIds, callback) => {
const { instanceUrl, token, siteaccess, accessToken } = getRestInfo();
const request = new Request(`${ENDPOINT_LOCATIONS_PERMISSIONS}?locationIds=${locationIds}`, {
method: 'GET',
headers: getRequestHeaders({
token,
siteaccess,
accessToken,
extraHeaders: {
Accept: 'application/json',
},
}),
mode: getRequestMode({ instanceUrl }),
credentials: 'same-origin',
});

fetch(request)
.then(handleRequestResponse)
.then(callback)
.catch(() => showErrorNotification('Cannot load locations permissions'));
Comment thread
OstafinL marked this conversation as resolved.
};

/**
* Updates location priority
*
Expand Down
34 changes: 28 additions & 6 deletions src/bundle/ui-dev/src/modules/sub-items/sub.items.module.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import PaginationInfo from '../common/pagination/pagination.info.js';

import deepClone from '../common/helpers/deep.clone.helper.js';
import { createCssClassNames } from '../common/helpers/css.class.names';
import { updateLocationPriority, loadLocation as loadLocationService } from './services/sub.items.service';
import { updateLocationPriority, loadLocation as loadLocationService, loadLocationsPermissions } from './services/sub.items.service';
import { bulkAddLocations, bulkDeleteItems, bulkHideLocations, bulkUnhideLocations, bulkMoveLocations } from './services/bulk.service.js';
import { VIEW_MODE_GRID, VIEW_MODE_TABLE } from './constants.js';

Expand Down Expand Up @@ -268,11 +268,33 @@ export default class SubItemsModule extends Component {
const { totalCount, pages, edges } = response.data._repository.location.children;
const activePageItems = edges.map((edge) => edge.node);

this.setState(() => ({
activePageItems,
totalCount,
pages,
}));
if (!activePageItems.length) {
this.setState(() => ({
activePageItems,
totalCount,
pages,
}));

return;
}

const locationIds = activePageItems.map((item) => item.id).join(',');

loadLocationsPermissions(locationIds, (permissionsResponse) => {
const permissionsByLocationId = permissionsResponse.LocationList.locations.reduce(
(permissionsMap, { location, permissions }) => ({
...permissionsMap,
[location.Location.id]: permissions,
}),
{},
);

this.setState(() => ({
activePageItems: activePageItems.map((item) => ({ ...item, permissions: permissionsByLocationId[item.id] })),
totalCount,
pages,
}));
});
});
}

Expand Down
Loading