Skip to content

Commit

Permalink
ENH Tidy up permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
emteknetnz committed Dec 18, 2023
1 parent 55208f8 commit 9d81374
Show file tree
Hide file tree
Showing 23 changed files with 380 additions and 139 deletions.
2 changes: 1 addition & 1 deletion client/dist/js/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/dist/styles/bundle.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions client/src/components/LinkField/LinkField.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const section = 'SilverStripe\\LinkField\\Controllers\\LinkFieldController';
* actions - object of redux actions
* isMulti - whether this field handles multiple links or not
*/
const LinkField = ({ value = null, onChange, types, actions, isMulti = false }) => {
const LinkField = ({ value = null, onChange, types, actions, isMulti = false, canCreate }) => {
const [data, setData] = useState({});
const [editingID, setEditingID] = useState(0);

Expand Down Expand Up @@ -145,6 +145,7 @@ const LinkField = ({ value = null, onChange, types, actions, isMulti = false })
typeTitle={type.title || ''}
onClear={onClear}
onClick={() => { setEditingID(linkID); }}
canDelete={data[linkID]?.canDelete ? true : false}
/>);
}
return links;
Expand All @@ -154,7 +155,7 @@ const LinkField = ({ value = null, onChange, types, actions, isMulti = false })
const renderModal = Boolean(editingID);

return <>
{ renderPicker && <LinkPicker onModalSuccess={onModalSuccess} onModalClosed={onModalClosed} types={types} /> }
{ renderPicker && <LinkPicker canCreate={canCreate} onModalSuccess={onModalSuccess} onModalClosed={onModalClosed} types={types} /> }
<div> { renderLinks() } </div>
{ renderModal && <LinkModalContainer
types={types}
Expand All @@ -174,6 +175,7 @@ LinkField.propTypes = {
types: PropTypes.objectOf(LinkType).isRequired,
actions: PropTypes.object.isRequired,
isMulti: PropTypes.bool,
canCreate: PropTypes.bool.isRequired,
};

// redux actions loaded into props - used to get toast notifications
Expand Down
13 changes: 11 additions & 2 deletions client/src/components/LinkPicker/LinkPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import LinkModalContainer from 'containers/LinkModalContainer';
/**
* Component which allows users to choose a type of link to create, and opens a modal form for it.
*/
const LinkPicker = ({ types, onModalSuccess, onModalClosed }) => {
const LinkPicker = ({ types, onModalSuccess, onModalClosed, canCreate }) => {
const [typeKey, setTypeKey] = useState('');

/**
Expand Down Expand Up @@ -41,9 +41,17 @@ const LinkPicker = ({ types, onModalSuccess, onModalClosed }) => {
const className = classnames('link-picker', 'form-control');
const typeArray = Object.values(types);

if (!canCreate) {
return (
<div className={className}>
<div className="link-picker__cannot-create">Cannot create link</div>
</div>
);
}

return (
<div className={className}>
<LinkPickerMenu types={typeArray} onSelect={handleSelect} />
<LinkPickerMenu types={typeArray} onSelect={handleSelect} canCreate={canCreate} />
{ shouldOpenModal && <LinkModalContainer
types={types}
typeKey={typeKey}
Expand All @@ -60,6 +68,7 @@ LinkPicker.propTypes = {
types: PropTypes.objectOf(LinkType).isRequired,
onModalSuccess: PropTypes.func.isRequired,
onModalClosed: PropTypes.func,
canCreate: PropTypes.bool.isRequired
};

export {LinkPicker as Component};
Expand Down
6 changes: 6 additions & 0 deletions client/src/components/LinkPicker/LinkPicker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
}
}

.link-picker__cannot-create {
cursor: default;
flex-grow: 1;
padding: 16px 13px;
}

.link-picker__menu {
flex-grow: 1;
}
Expand Down
38 changes: 22 additions & 16 deletions client/src/components/LinkPicker/LinkPickerMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,35 @@ import PropTypes from 'prop-types';
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
import LinkType from 'types/LinkType';

const LinkPickerMenu = ({ types, onSelect }) => {
const LinkPickerMenu = ({ types, onSelect, canCreate }) => {
const [isOpen, setIsOpen] = useState(false);
const toggle = () => setIsOpen(prevState => !prevState);

return (
<Dropdown
isOpen={isOpen}
toggle={toggle}
className="link-picker__menu"
>
<DropdownToggle className="link-picker__menu-toggle font-icon-plus-1" caret>{i18n._t('LinkField.ADD_LINK', 'Add Link')}</DropdownToggle>
<DropdownMenu>
{types.map(({key, title}) =>
<DropdownItem key={key} onClick={() => onSelect(key)}>{title}</DropdownItem>
)}
</DropdownMenu>
</Dropdown>
);
return <>
{ canCreate &&
<Dropdown
isOpen={isOpen}
toggle={toggle}
className="link-picker__menu"
>
<DropdownToggle className="link-picker__menu-toggle font-icon-plus-1" caret>{i18n._t('LinkField.ADD_LINK', 'Add Link')}</DropdownToggle>
<DropdownMenu>
{types.map(({key, title}) =>
<DropdownItem key={key} onClick={() => onSelect(key)}>{title}</DropdownItem>
)}
</DropdownMenu>
</Dropdown>
}
{ !canCreate &&
<div className="link-picker__cannot-create">Cannot create link</div>
}
</>;
};

LinkPickerMenu.propTypes = {
types: PropTypes.arrayOf(LinkType).isRequired,
onSelect: PropTypes.func.isRequired
onSelect: PropTypes.func.isRequired,
canCreate: PropTypes.bool.isRequired,
};

export default LinkPickerMenu;
16 changes: 14 additions & 2 deletions client/src/components/LinkPicker/LinkPickerTitle.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,16 @@ const getVersionedBadge = (versionState) => {
return <span className={className} title={title}>{label}</span>;
};

const LinkPickerTitle = ({ id, title, description, versionState, typeTitle, onClear, onClick }) => {
const LinkPickerTitle = ({
id,
title,
description,
versionState,
typeTitle,
onClear,
onClick,
canDelete
}) => {
const classes = {
'link-picker__link': true,
'form-control': true,
Expand All @@ -54,7 +63,9 @@ const LinkPickerTitle = ({ id, title, description, versionState, typeTitle, onCl
</small>
</div>
</Button>
<Button className="link-picker__clear" color="link" onClick={stopPropagation(() => onClear(id))}>{i18n._t('LinkField.CLEAR', 'Clear')}</Button>
{canDelete &&
<Button className="link-picker__clear" color="link" onClick={stopPropagation(() => onClear(id))}>{i18n._t('LinkField.CLEAR', 'Clear')}</Button>
}
</div>
};

Expand All @@ -66,6 +77,7 @@ LinkPickerTitle.propTypes = {
typeTitle: PropTypes.string.isRequired,
onClear: PropTypes.func.isRequired,
onClick: PropTypes.func.isRequired,
canDelete: PropTypes.bool.isRequired,
};

export default LinkPickerTitle;
1 change: 1 addition & 0 deletions client/src/entwine/LinkField.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ jQuery.entwine('ss', ($) => {
value,
onChange: this.handleChange.bind(this),
isMulti: this.data('is-multi') ?? false,
canCreate: this.getInputField().data('can-create') ?? false,
};
},

Expand Down
1 change: 1 addition & 0 deletions src/Controllers/LinkFieldController.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ private function getLinkData(Link $link): array
$this->jsonError(403, _t('LinkField.UNAUTHORIZED', 'Unauthorized'));
}
$data = $link->jsonSerialize();
$data['canDelete'] = $link->canDelete();
$data['description'] = $link->getDescription();
$data['versionState'] = $link->getVersionedState();
return $data;
Expand Down
8 changes: 8 additions & 0 deletions src/Form/LinkField.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,18 @@ public function saveInto(DataObjectInterface $record)
return $this;
}

public function getSchemaStateDefaults()
{
$data = parent::getSchemaStateDefaults();
$data['canCreate'] = !$this->isReadonly();
return $data;
}

protected function getDefaultAttributes(): array
{
$attributes = parent::getDefaultAttributes();
$attributes['data-value'] = $this->Value();
$attributes['data-can-create'] = !$this->isReadonly();
return $attributes;
}
}
3 changes: 3 additions & 0 deletions src/Form/MultiLinkField.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use SilverStripe\ORM\RelationList;
use SilverStripe\ORM\SS_List;
use SilverStripe\ORM\UnsavedRelationList;
use SilverStripe\LinkField\Models\Link;

/**
* Allows CMS users to edit a Link object.
Expand Down Expand Up @@ -68,13 +69,15 @@ public function getSchemaStateDefaults()
{
$data = parent::getSchemaStateDefaults();
$data['value'] = $this->getValueArray();
$data['canCreate'] = !$this->isReadonly();
return $data;
}

protected function getDefaultAttributes(): array
{
$attributes = parent::getDefaultAttributes();
$attributes['data-value'] = $this->getValueArray();
$attributes['data-can-create'] = !$this->isReadonly();
return $attributes;
}

Expand Down
6 changes: 5 additions & 1 deletion src/Models/FileLink.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ public function getCMSFields(): FieldList

public function getDescription(): string
{
return $this->File()?->getFilename() ?? '';
$file = $this->File();
if (!$file?->exists() || !$file->canView()) {
return '';
}
return $file->getFilename() ?? '';
}

public function getURL(): string
Expand Down
14 changes: 9 additions & 5 deletions src/Models/SiteTreeLink.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ class SiteTreeLink extends Link

public function getDescription(): string
{
return $this->Page()?->URLSegment ?? '';
$page = $this->Page();
if (!$page->exists() || !$page->canView()) {
return '';
}
return $page->URLSegment ?? '';
}

public function getCMSFields(): FieldList
Expand Down Expand Up @@ -113,15 +117,15 @@ public function getURL(): string
public function getDefaultTitle(): string
{
$page = $this->Page();
$pageExist = $this->Page()->exists();

if (!$pageExist) {
if (!$page->exists()) {
return _t(
static::class . '.MISSING_DEFAULT_TITLE',
'Page missing',
);
}

if (!$page->canView()) {
return '';
}
return $page->Title;
}
}
2 changes: 1 addition & 1 deletion templates/SilverStripe/LinkField/Form/MultiLinkField.ss
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<input $AttributesHTML />
<div data-is-multi="true" data-field-id="$ID" data-schema-component="$SchemaComponent" class="entwine-linkfield"></div>
<div data-is-multi="true" data-can-create="" data-field-id="$ID" data-schema-component="$SchemaComponent" class="entwine-linkfield"></div>
Loading

0 comments on commit 9d81374

Please sign in to comment.