Skip to content

Commit

Permalink
ENHANCEMENT Enable UploadField.js within non-react sections (#331)
Browse files Browse the repository at this point in the history
* ENHANCEMENT Enable UploadField.js within non-react sections

* Implement feedback
  • Loading branch information
Damian Mooyman authored and chillu committed Dec 19, 2016
1 parent 2d1b572 commit 802e604
Show file tree
Hide file tree
Showing 16 changed files with 299 additions and 70 deletions.
119 changes: 63 additions & 56 deletions client/dist/js/bundle.js

Large diffs are not rendered by default.

18 changes: 17 additions & 1 deletion client/dist/styles/bundle.css
Original file line number Diff line number Diff line change
Expand Up @@ -506,10 +506,26 @@
cursor:pointer;
}

.uploadfield__add-button,.uploadfield__upload-button{
border:0;
margin:0;
padding:0;
background:none;
text-decoration:none;
color:#0071c4;
}

.uploadfield__add-button:hover,.uploadfield__upload-button:hover{
color:#0062ab;
text-decoration:underline;
}

.uploadfield__droptext{
position:absolute;
top:20px;
left:40%;
left:50%;
-webkit-transform:translateX(-50%);
transform:translateX(-50%);
display:inline-block;
text-align:center;
}
Expand Down
3 changes: 1 addition & 2 deletions client/src/boot/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ import uploadFieldReducer from 'state/uploadField/UploadFieldReducer';
import Injector from 'lib/Injector';
import UploadField from 'components/UploadField/UploadField';
import HistoryList from 'containers/HistoryList/HistoryList';
import injector from 'lib/Injector';

document.addEventListener('DOMContentLoaded', () => {
Injector.register('UploadField', UploadField);
Injector.register('HistoryList', HistoryList);

const sectionConfig = Config.getSection('SilverStripe\\AssetAdmin\\Controller\\AssetAdmin');

injector.register('HistoryList', HistoryList);

reactRouteRegister.add({
path: sectionConfig.url,
Expand Down
1 change: 1 addition & 0 deletions client/src/bundles/bundle.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require('expose?InsertMediaModal!containers/InsertMediaModal/InsertMediaModal');

require('boot');
require('entwine/UploadField/UploadFieldEntwine.js');

require('styles/bundle.scss');
14 changes: 8 additions & 6 deletions client/src/components/UploadField/UploadField.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,15 @@ class UploadField extends SilverStripeComponent {
>
<div className="uploadfield__backdrop"></div>
<span className="uploadfield__droptext">
<a href="#" onClick={this.handleSelect} className="uploadfield__upload-button">
<button onClick={this.handleSelect} className="uploadfield__upload-button">
{i18n._t('AssetAdminUploadField.BROWSE', 'Browse')}
</a>
</button>
{' '}
{i18n._t('AssetAdminUploadField.OR', 'or')}
{' '}
<a href="#" onClick={this.handleAddShow} className="uploadfield__add-button">
<button onClick={this.handleAddShow} className="uploadfield__add-button">
{i18n._t('AssetAdminUploadField.ADD_FILES', 'Add from files')}
</a>
</button>
</span>
</AssetDropzone>
);
Expand Down Expand Up @@ -326,6 +326,8 @@ function mapDispatchToProps(dispatch) {
};
}

export { UploadField };
const ConnectedUploadField = connect(mapStateToProps, mapDispatchToProps)(UploadField);

export default fieldHolder(connect(mapStateToProps, mapDispatchToProps)(UploadField));
export { UploadField, ConnectedUploadField };

export default fieldHolder(ConnectedUploadField);
18 changes: 17 additions & 1 deletion client/src/components/UploadField/UploadField.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,26 @@
cursor: pointer;
}

.uploadfield__upload-button,
.uploadfield__add-button {
border: 0;
margin: 0;
padding: 0;
background: none;
text-decoration: $link-decoration;
color: $link-color;

&:hover {
color: $link-hover-color;
text-decoration: $link-hover-decoration;
}
}

.uploadfield__droptext {
position: absolute;
top: 20px;
left: 40%;
left: 50%;
transform: translateX(-50%);
display: inline-block;
text-align: center;

Expand Down
6 changes: 3 additions & 3 deletions client/src/containers/Gallery/Gallery.js
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,8 @@ class Gallery extends Component {
this.props.actions.queuedFiles.removeQueuedFile(fileXhr._queuedId);
this.props.actions.gallery.addFiles(json, this.props.count + 1);

// redirect to open the last uploaded file for 'insert modal' type only
if (this.props.type === 'insert'
// redirect to open the last uploaded file for 'insert/select modal' type only
if (this.props.type !== 'admin'
&& !this.props.fileId
&& this.props.queuedFiles.items.length === 0
) {
Expand Down Expand Up @@ -736,7 +736,7 @@ Gallery.defaultProps = Object.assign({}, sharedDefaultProps, {
});

Gallery.propTypes = Object.assign({}, sharedPropTypes, {
type: PropTypes.oneOf(['insert', 'admin']),
type: PropTypes.oneOf(['insert', 'select', 'admin']),
view: PropTypes.oneOf(['tile', 'table']),
dialog: PropTypes.bool,
fileId: PropTypes.number,
Expand Down
50 changes: 50 additions & 0 deletions client/src/entwine/UploadField/UploadFieldEntwine.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import jQuery from 'jQuery';
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { schemaMerge } from 'lib/schemaFieldValues';
import { ConnectedUploadField } from 'components/UploadField/UploadField';

/**
* Shiv for inserting react UploadField into entwine forms
*/
jQuery.entwine('ss', ($) => {
/**
* See boot/index.js for `.react-boot` bootstrap
*/
$('.js-react-boot input.entwine-uploadfield').entwine({

onunmatch() {
this._super();
// solves errors given by ReactDOM "no matched root found" error.
ReactDOM.unmountComponentAtNode(this[0]);
},

onmatch() {
this._super();
this.refresh();
},

refresh() {
const store = window.ss.store;
const props = this.getAttributes();
ReactDOM.render(
<Provider store={store}>
<ConnectedUploadField {...props} />
</Provider>,
this.parent()[0]
);
},

/**
* Find the selected node and get attributes associated to attach the data to the form
*
* @returns {Object}
*/
getAttributes() {
const state = $(this).data('state');
const schema = $(this).data('schema');
return schemaMerge(schema, state);
},
});
});
23 changes: 23 additions & 0 deletions code/Forms/UploadField.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,27 @@ public function setIsMultiUpload($multi)
$this->multiUpload = $multi;
return $this;
}

public function getAttributes()
{
$attributes = array(
'class' => $this->extraClass(),
'type' => 'file',
'multiple' => $this->getIsMultiUpload(),
'id' => $this->ID(),
'data-schema' => json_encode($this->getSchemaData()),
'data-state' => json_encode($this->getSchemaState()),
);

$attributes = array_merge($attributes, $this->attributes);

$this->extend('updateAttributes', $attributes);

return $attributes;
}

public function Type()
{
return 'entwine-uploadfield uploadfield';
}
}
1 change: 1 addition & 0 deletions templates/SilverStripe/AssetAdmin/Forms/UploadField.ss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<input $AttributesHTML <% include SilverStripe/Forms/AriaAttributes %> />
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace SilverStripe\AssetAdmin\Tests;
namespace SilverStripe\AssetAdmin\Tests\Forms;

use SilverStripe\AssetAdmin\Controller\AssetAdmin;
use SilverStripe\AssetAdmin\Forms\FileFormFactory;
Expand Down Expand Up @@ -34,6 +34,12 @@ public function setUp()
$testimage->setFromLocalFile(__DIR__.'/fixtures/testimage.png', 'files/testimage.png');
}

public function tearDown()
{
TestAssetStore::reset();
parent::tearDown();
}

public function testEditFileForm()
{
$this->logInWithPermission('ADMIN');
Expand Down
File renamed without changes.
107 changes: 107 additions & 0 deletions tests/php/Forms/UploadFieldTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace SilverStripe\AssetAdmin\Tests\Forms;

use SilverStripe\AssetAdmin\Controller\AssetAdmin;
use SilverStripe\Assets\File;
use SilverStripe\AssetAdmin\Forms\UploadField;
use SilverStripe\Assets\Image;
use SilverStripe\Assets\Tests\Storage\AssetStoreTest\TestAssetStore;
use SilverStripe\Control\Controller;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\ORM\ArrayList;

class UploadFieldTest extends SapphireTest
{
protected static $fixture_file = 'FileFormBuilderTest.yml';

public function setUp()
{
parent::setUp();

// Set backend and base url
TestAssetStore::activate('FileFormBuilderTest');

/** @var File $testfile */
$testfile = $this->objFromFixture(File::class, 'file1');
$testfile->setFromLocalFile(__DIR__ . '/fixtures/testfile.txt', 'files/testfile.txt');
$testfile->write();

/** @var Image $testimage */
$testimage = $this->objFromFixture(Image::class, 'image1');
$testimage->setFromLocalFile(__DIR__ . '/fixtures/testimage.png', 'files/testimage.png');
}

public function tearDown()
{
TestAssetStore::reset();
parent::tearDown();
}

public function testGetAttributes()
{
$field = UploadField::create('MyField');
$field->addExtraClass('myfield');
$field->setIsMultiUpload(false);
$field->setFolderName('/');
/** @var Image $image */
$image = $this->objFromFixture(Image::class, 'image1');
$field->setItems(new ArrayList([$image]));
Form::create(new Controller(), 'MyForm', FieldList::create($field), FieldList::create());
$admin = new AssetAdmin();

$attributes = $field->getAttributes();
$schema = [
'name' => 'MyField',
'id' => 'Form_MyForm_MyField',
'type' => 'Custom',
'component' => 'UploadField',
'holderId' => 'Form_MyForm_MyField_Holder',
'title' => 'My Field',
'source' => null,
'extraClass' => 'entwine-uploadfield uploadfield myfield',
'description' => null,
'rightTitle' => null,
'leftTitle' => null,
'readOnly' => false,
'disabled' => false,
'customValidationMessage' => '',
'validation' => [],
'attributes' => [],
'data' => [
'createFileEndpoint' => [
'url' => 'admin/assets/api/createFile',
'method' => 'post',
'payloadFormat' => 'urlencoded',
],
'multi' => false,
'parentid' => 0,
],
];
$state = [
'name' => 'MyField',
'id' => 'Form_MyForm_MyField',
'value' => [ 'Files' => [$image->ID] ],
'message' => null,
'data' => [
'files' => [ $admin->getObjectFromData($image) ],
],
];
$this->assertArraySubset(
[
'class' => 'entwine-uploadfield uploadfield myfield',
'type' => 'file',
'multiple' => false,
'id' => 'Form_MyForm_MyField'
],
$attributes
);

// Check schema / state are encoded in this field
$this->assertEquals($schema, json_decode($attributes['data-schema'], true));
$this->assertEquals($state, json_decode($attributes['data-state'], true));
}
}
File renamed without changes.
File renamed without changes
1 change: 1 addition & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ module.exports = {
'state/schema/SchemaActions': 'SchemaActions',
'components/FieldHolder/FieldHolder': 'FieldHolder',
'lib/DataFormat': 'DataFormat',
'lib/schemaFieldValues': 'schemaFieldValues',
'components/FormBuilderModal/FormBuilderModal': 'FormBuilderModal',
'components/FormBuilder/FormBuilder': 'FormBuilder',
'components/Toolbar/Toolbar': 'Toolbar',
Expand Down

0 comments on commit 802e604

Please sign in to comment.