Source: 04-CPlainUploadColumn.jsx

  1. /**
  2. * Plain upload column.
  3. *
  4. * Simple column for uploading files.
  5. *
  6. * @arg {string} this.props.upload_endpoint - Endpoint for uploading files.
  7. * @arg {string} this.props.links_endpoint - Endpoint for links to files.
  8. * @arg {undefined | int} this.props.max_file_size - Maximum file size.
  9. * @arg {undefined | string[]} this.props.allowed_extentions - Allowed file extention.
  10. */
  11. class CPlainUploadColumn extends CTableColumn{
  12. constructor() {
  13. super();
  14. this.filterChanged = this.filterChanged.bind(this);
  15. this.uploadChanged = this.uploadChanged.bind(this);
  16. this.editorChanged = this.editorChanged.bind(this);
  17. this.editorCleared = this.editorCleared.bind(this);
  18. this.ref = createRef();
  19. }
  20. componentDidMount() {
  21. this.setState({value: this.value()});
  22. }
  23. render_cell() {
  24. if (!this.value()){
  25. return <a class="button is-info" disabled="true"><span class="material-icons">attach_file</span> {this.props.table.props.lang.no_file}</a>;
  26. }
  27. if (typeof this.props.links_endpoint === 'undefined'){
  28. return <a class="button is-info"><span class="material-icons">attach_file</span>{this.props.table.props.lang.file_present}</a>;
  29. }
  30. return <a class="button is-info" href={this.props.links_endpoint + this.value()}><span class="material-icons">attach_file</span>{this.props.table.props.lang.file_present}</a>;
  31. }
  32. filterChanged(e){
  33. if(e.target.value == ''){
  34. this.props.table.change_filter_for_column(this.props.column, null);
  35. } else {
  36. this.props.table.change_filter_for_column(this.props.column, e.target.value);
  37. }
  38. this.setState({value: e.target.value});
  39. }
  40. render_search() {
  41. if (typeof this.props.filtering === 'undefined') {
  42. // do nothing
  43. } else {
  44. return <div class="select">
  45. <select onChange={this.filterChanged} value={this.props.filtering}>
  46. <option value=''>{this.props.table.props.lang.no_filter}</option>
  47. <option value='%nodata'>{this.props.table.props.lang.file_filter_no}</option>
  48. <option value='%notempty'>{this.props.table.props.lang.file_filter_yes}</option>
  49. </select>
  50. </div>;
  51. }
  52. }
  53. editorChanged(e) {
  54. this.props.table.notify_changes(this.props.row, this.props.column, e.target.value);
  55. this.setState({value: e.target.value});
  56. }
  57. editorCleared() {
  58. this.props.table.notify_changes(this.props.row, this.props.column, "");
  59. this.setState({value: ""});
  60. }
  61. uploadChanged(e) {
  62. var form_data = new FormData();
  63. if(e.target.files.length != 1){
  64. alert(this.props.table.props.lang.file_only_one);
  65. return;
  66. }
  67. if(this.props.max_file_size){
  68. if(e.target.files[0].size > this.props.max_file_size){
  69. alert(this.props.table.props.lang.file_to_large);
  70. return;
  71. }
  72. }
  73. if(this.props.allowed_extentions){
  74. if (this.props.allowed_extentions.filter(item => e.target.files[0].name.toLowerCase().endsWith(item)).length == 0){
  75. alert(this.props.table.props.lang.file_wrong_extention);
  76. return;
  77. }
  78. }
  79. form_data.append("file", e.target.files[0]);
  80. var self = this;
  81. var xkeys = {};
  82. this.props.table.state.columns.map(function (item, i) {
  83. if(item.is_key == true && self.props.row >= 0){
  84. xkeys[item.name] = self.props.table.state.records[self.props.row][item.name];
  85. }
  86. });
  87. form_data.append("keys", JSON.stringify(xkeys));
  88. this.props.table.setState({waiting_active: true});
  89. fetch(this.props.upload_endpoint, {method: 'POST', body: form_data})
  90. .then(function(response){
  91. self.props.table.setState({waiting_active: false}); // always disable table waiting
  92. if (response.ok) {return response.json();}
  93. else {alert(self.props.table.props.lang.server_error + response.status)} })
  94. .then(function (result) {
  95. if (!result) return;
  96. if(result.Result == 'OK'){
  97. self.props.table.notify_changes(self.props.row, self.props.column, result.Filename);
  98. self.setState({value: result.Filename});
  99. }
  100. if(result.Result == 'Error'){
  101. alert(result.Message);
  102. }});
  103. }
  104. render_editor() {
  105. return <><label class="label">{this.title()}</label>
  106. <div class="field has-addons">
  107. <div class="control">
  108. <input class="input" value={this.state.value} onChange={this.editorChanged}></input>
  109. </div>
  110. <div class="control">
  111. <a class="button is-info" target="_blank" href={this.state.value === null || this.state.value === '' ? false : this.props.links_endpoint + this.state.value} disabled={this.state.value === null || this.state.value === '' ? true : false}><span class="material-icons">attach_file</span></a>
  112. </div>
  113. <div class="control">
  114. <button class="button is-info"><span class="material-icons">upload</span></button>
  115. <input class="file-input" type="file" name="file" onChange={this.uploadChanged}/>
  116. </div>
  117. <div class="control">
  118. <button class="button is-danger" onClick={this.editorCleared}><span class="material-icons">cancel</span></button>
  119. </div>
  120. </div>
  121. {this.props.footnote ? <div class="help">{this.props.footnote}</div> : ''}
  122. </>;
  123. }
  124. }