Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 51482e8c

Von Sven Schöling vor mehr als 3 Jahren hinzugefügt

  • ID 51482e8c993805f628178762436da76ff798d2ca
  • Vorgänger 12236962
  • Nachfolger d3412c6d

ImageUpload: local storage erste Version

Unterschiede anzeigen:

SL/Controller/ImageUpload.pm
28 28
  my ($self) = @_;
29 29

  
30 30
  $::request->layout->add_javascripts('kivi.File.js');
31
  $::request->layout->add_javascripts('kivi.FileDB.js');
32
  $::request->layout->add_javascripts('kivi.ImageUpload.js');
31 33

  
32
  $self->render('image_upload/form');
34
  $self->render('image_upload/local_list');
33 35
}
34 36

  
35 37
################# internal ###############
js/kivi.FileDB.js
1
namespace("kivi.FileDB", function(ns) {
2
  "use strict";
3

  
4
  const database = 'kivi';
5
  const store    = 'files';
6
  const db_version = 1;
7

  
8
  // IndexedDB
9
  const indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB;
10

  
11
  // Create/open database
12
  let db;
13
  let request = indexedDB.open(database, db_version);
14
  request.onupgradeneeded = (event) => {
15
    ns.create_image_store(event.target.result);
16
  };
17
  request.onerror = ns.onerror;
18
  request.onsuccess = () => {
19
    db = request.result;
20

  
21
    db.onerror = (event) => {
22
      console.error("Error creating/accessing IndexedDB database");
23
      console.error(event);
24
    };
25

  
26
    // Interim solution for Google Chrome to create an objectStore. Will be deprecated
27
    if (db.setVersion) {
28
      if (db.version != db_version) {
29
        let setVersion = db.setVersion(db_version);
30
        setVersion.onsuccess = () =>  {
31
          ns.create_image_store(db);
32
        };
33
      }
34
    }
35
  };
36

  
37
  ns.create_image_store = function (db) {
38
    db.createObjectStore(store, { autoIncrement : true });
39
  };
40

  
41
  ns.store_image = function (blob, filename, success) {
42
    let put_request = ns.open_store("readwrite").add(blob, filename);
43

  
44
    put_request.onsuccess = success;
45
    put_request.on_error = ns.onerror;
46
  };
47

  
48
  ns.retrieve_image = function(key, success) {
49
    let get_request = ns.open_store().objectStore(store).get(key);
50

  
51
    get_request.onsuccess = success;
52
    get_request.onerror = request.onerror;
53
  };
54

  
55
  ns.retrieve_all = function(success) {
56
    let request = ns.open_store().getAll();
57
    request.onsuccess = (event) => { success(event.target.result); };
58
    request.onerror = ns.error;
59
  };
60

  
61
  ns.retrieve_all_keys = function(success) {
62
    let request = ns.open_store().getAllKeys();
63
    request.onsuccess = (event) => { success(event.target.result); };
64
    request.onerror = ns.error;
65
  };
66

  
67
  ns.delete_all= function() {
68
    ns.retrieve_all_keys((keys) => {
69
      keys.forEach((key) => ns.delete_key(key));
70
    });
71
  };
72

  
73
  ns.delete_key= function(key, success) {
74
    let request = ns.open_store("readwrite").delete(key);
75
    request.onsuccess = (event) => { if (success) success(event.target.result); };
76
    request.onerror = ns.error;
77
  };
78

  
79
  ns.open_store = function(mode = "readonly")  {
80
    return db.transaction([store], mode).objectStore(store);
81
  };
82

  
83
  ns.onerror = (event) => {
84
    console.error("Error creating/accessing IndexedDB database");
85
    console.error(event.errorState);
86
  };
87
});
js/kivi.ImageUpload.js
1
namespace("kivi.ImageUpload", function(ns) {
2
  "use strict";
3

  
4
  ns.add_files = function(target) {
5
    let files = [];
6
    for (var i = 0; i < target.files.length; i++) {
7
      files.push(target.files.item(i));
8
    }
9

  
10
    kivi.FileDB.store_image(files[0], files[0].name, () => {
11
      ns.reload_images();
12
      target.value = null;
13
    });
14
  };
15

  
16
  ns.reload_images = function() {
17
    kivi.FileDB.retrieve_all((data) => {
18
      $('#stored-images').empty();
19
      data.forEach(ns.create_thumb_row);
20
    });
21
  };
22

  
23
  ns.create_thumb_row = function(file)  {
24
    let URL = window.URL || window.webkitURL;
25
    let file_url = URL.createObjectURL(file);
26

  
27
    let $row = $("<div>").addClass("row image-upload-row");
28
    let $button = $("<a>")
29
      .addClass("btn-floating btn-large waves-effect waves-light red")
30
      .click((event) => ns.remove_image(event, file.name))
31
      .append($("<i>delete</i>").addClass("material-icons"));
32
    $row.append($("<div>").addClass("col s3").append($button));
33

  
34
    let $image = $('<img>').attr("src", file_url).addClass("materialboxed responsive-img");
35
    $row.append($("<div>").addClass("col s9").append($image));
36

  
37
    $("#stored-images").append($row);
38
  };
39

  
40
  ns.remove_image = function(event, key) {
41
    let $row = $(event.target).closest(".image-upload-row");
42
    kivi.FileDB.delete_key(key, () => {
43
      $row.remove();
44
    });
45
  };
46

  
47
  ns.upload_selected_files = function(id,type,filetype,maxsize) {
48
    kivi.FileDB.retrieve_all((myfiles) => {
49
      let filesize  = 0;
50
      myfiles.forEach(file => {
51
        filesize  += file.size;
52
        if (filesize > maxsize) {
53
          $("#upload_result").html(kivi.t8("filesize too big: ") + filesize+ kivi.t8(" bytes, max=") + maxsize );
54
          return;
55
        }
56

  
57
        let data = new FormData();
58
        data.append(file);
59
        data.append("action", "File/ajax_files_uploaded");
60
        data.append("json", "1");
61
        data.append("object_type", type);
62
        data.append("object_id", id);
63
        data.append("file_type", filetype);
64

  
65
        $("#upload_result").html(kivi.t8("start upload"));
66

  
67
        $.ajax({
68
          url: "controller.pl",
69
          data: data,
70
          success: ns.attSuccess,
71
          progress: ns.attProgress,
72
          error: ns.attFailes,
73
          abort: ns.attCanceled
74
        });
75
      });
76
    });
77
  };
78

  
79
  ns.attProgress = function(event) {
80
    if (event.lengthComputable) {
81
      var percentComplete = (event.loaded / event.total) * 100;
82
      $("#upload_result").html(percentComplete+" % "+ kivi.t8("uploaded"));
83
    }
84
  };
85

  
86
  ns.attFailed = function() {
87
    $('#upload_modal').modal('close');
88
    $("#upload_result").html(kivi.t8("An error occurred while transferring the file."));
89
  };
90

  
91
  ns.attCanceled = function() {
92
    $('#upload_modal').modal('close');
93
    $("#upload_result").html(kivi.t8("The transfer has been canceled by the user."));
94
  };
95

  
96
  ns.attSuccess = function() {
97
    $('#upload_modal').modal('close');
98
    $("#upload_result").html(kivi.t8("Files have been uploaded successfully."));
99
  };
100

  
101
  ns.init = function() {
102
    ns.reload_images();
103
  };
104

  
105

  
106
});
107

  
108
$(kivi.ImageUpload.init);
js/kivi.Materialize.js
3 3

  
4 4
  ns.init = function() {
5 5
    ns.reinit_widgets();
6
  }
6
  };
7 7

  
8
  ns.build_i18n = function(locale) {
8
  ns.build_i18n = function() {
9 9
    return {
10 10
      months: [
11 11
        kivi.t8('January'),
......
63 63
      // Accessibility labels
64 64
      labelMonthNext: kivi.t8('Next month'),
65 65
      labelMonthPrev: kivi.t8('Previous month')
66
    }
67
  }
66
    };
67
  };
68 68

  
69 69
  ns.reinit_widgets = function() {
70 70
    $('.sidenav').sidenav();
......
76 76
      i18n: ns.build_i18n()
77 77
    });
78 78
    $('.modal').modal();
79
    $('.materialboxed').materialbox();
79 80
    M.updateTextFields();
80
  }
81
  };
81 82

  
82 83
  // alternative for kivi.popup_dialog.
83 84
  // opens materialize modal instead.
84 85
  //
85 86
  // differences: M.modal can not load external content, so it needs to be fetched manually and inserted into the DOM.
86 87
  ns.popup_dialog = function(params) {
87
    console.log(params);
88 88
    params            = params        || { };
89 89
    let id            = params.id     || 'jqueryui_popup_dialog';
90 90
    let $div;
......
94 94
        // unlike classic layout, there is not fixed size, and M.modal is always... modal
95 95
        onCloseStart: custom_close
96 96
      },
97
        // User supplied options:
97
      // User supplied options:
98 98
      params.dialog || { },
99 99
      { // Options that must not be changed:
100 100
        // close options already work
......
110 110
          params.data = undefined;
111 111
          ns.popup_dialog(params);
112 112
        },
113
        error: function(x, status, error) { console.log(error); },
113
        error: function(x, status, error) { console.error(error); },
114 114
        dataType: 'text',
115 115
      });
116 116
      return 1;
......
118 118

  
119 119
    if (params.html) {
120 120
      $div = $('<div>');
121
      $div.attr('id', id)
121
      $div.attr('id', id);
122 122
      $div.addClass("modal");
123 123
      let $modal_content = $('<div>');
124 124
      $modal_content.addClass('modal-content');
......
126 126
      $div.append($modal_content);
127 127
      $('body').append($div);
128 128
      kivi.reinit_widgets();
129
      dialog_params.onCloseEnd = function() { $div.remove(); }
129
      dialog_params.onCloseEnd = function() { $div.remove(); };
130 130

  
131 131
      $div.modal(dialog_params);
132

  
133 132
    } else if(params.id) {
134 133
      $div = $('#' + params.id);
135 134
    } else {
......
140 139
    $div.modal('open');
141 140

  
142 141
    return true;
142
  };
143

  
144
  /**
145
   * upload file to local storage for later sync
146
   *
147
   * should be used with P.M.file_upload(..., local=>1)
148
   */
149
  ns.LocalFileUpload = function(options) {
150
    this.storage_token = options.storage_token; // used in localstorage to retrieve the file
151
    this.dom_selector  = options.dom_selector;  // file inputs to listen on
152

  
153
    this.init();
154
  };
155

  
156
  ns.LocalFileUpload.prototype = {
157
    init: function() {
158
      $(this.dom_selector).change(this.handle_file_upload);
159
    },
160
    handle_file_upload: function() {
161

  
162
    },
163
    load_files: function() {
164
      return JSON.parse(localStorage.getImte(this.storage_token));
165
    },
166
    save_files: function() {
167
      return JSON.parse(localStorage.getImte(this.storage_token));
168
    },
169

  
170
  };
143 171

  
144
  }
145 172
});
package.json
1
{
2
  "name": "dev",
3
  "version": "1.0.0",
4
  "description": "",
5
  "main": "index.js",
6
  "directories": {
7
    "doc": "doc"
8
  },
9
  "scripts": {
10
    "test": "echo \"Error: no test specified\" && exit 1"
11
  },
12
  "repository": {
13
    "type": "git",
14
    "url": "git+https://github.com/kivitendo/kivitendo-erp.git"
15
  },
16
  "author": "",
17
  "license": "ISC",
18
  "bugs": {
19
    "url": "https://github.com/kivitendo/kivitendo-erp/issues"
20
  },
21
  "homepage": "https://github.com/kivitendo/kivitendo-erp#readme"
22
}
templates/mobile_webpages/image_upload/local_list.html
1
[%- USE LxERP -%] [%- USE L %]
2
[%- USE HTML %]
3
[%- USE P %]
4
[%- USE T8 %]
5

  
6
<h4>[% source.title | html %]</h4>
7

  
8
  <div id="updoad_result"></div>
9

  
10
  <div id="stored-images" class="container">
11
  </div>
12

  
13

  
14
  <div class="container">
15
    <div class="row">
16

  
17
      <div class="file-field input-field col">
18
        <div class="btn m3 s12">
19
          <span>[% 'Upload Image' | $T8 %]</span>
20
          <input
21
            name="uploadfiles[]" type="file" [% IF multiple %]multiple[% END %]
22
            id="upload_files" accept="[% SELF.accept_types %]" capture="camera"
23
            onchange="kivi.ImageUpload.add_files(this)">
24
        </div>
25
        <div class="file-path-wrapper m9 s12">
26
          <input class="file-path validate" type="hidden">
27
        </div>
28
      </div>
29

  
30
    </div>
31

  
32
    <div class="row">
33
      [% P.M.input_tag("object_number", "", label=LxERP.t8("Number")) %]
34
      [% P.M.button_tag("submit", LxERP.t8("Upload")) %]
35
    </div>
36

  
37

  
38
    </div>
39
  </div>
40

  
41
<div id="upload_modal" class="modal">
42
  <div class="modal-content">
43
    <h4>Uploading</h4>
44

  
45
    <p>A bunch of text</p>
46
  </div>
47
</div>

Auch abrufbar als: Unified diff