Rafał Pitoń 9 лет назад
Родитель
Сommit
74bd255edd

+ 2 - 1
misago/frontend/misago/app.js

@@ -46,7 +46,8 @@
     this.init = function(setup) {
     this.init = function(setup) {
       this.setup = {
       this.setup = {
         fixture: ns.get(setup, 'fixture', null),
         fixture: ns.get(setup, 'fixture', null),
-        inTest: ns.get(setup, 'inTest', false)
+        inTest: ns.get(setup, 'inTest', false),
+        api: ns.get(setup, 'api', '/api/')
       };
       };
 
 
       this._initServices(ns._services);
       this._initServices(ns._services);

+ 9 - 2
misago/frontend/misago/models/ban.js

@@ -1,7 +1,7 @@
 (function (Misago) {
 (function (Misago) {
   'use strict';
   'use strict';
 
 
-  Misago.Ban = function(data) {
+  var Ban = function(data) {
     this.message = {
     this.message = {
       html: data.message.html,
       html: data.message.html,
       plain: data.message.plain,
       plain: data.message.plain,
@@ -10,9 +10,16 @@
     this.expires_on = data.expires_on;
     this.expires_on = data.expires_on;
   };
   };
 
 
-  Misago.Ban.deserialize = function(data) {
+  var deserializeBan = function(data) {
     data.expires_on = Misago.deserializeDatetime(data.expires_on);
     data.expires_on = Misago.deserializeDatetime(data.expires_on);
 
 
     return new Misago.Ban(data);
     return new Misago.Ban(data);
   };
   };
+
+  Misago.addService('ban-model', function(_) {
+    _.models.add('ban', {
+      class: Ban,
+      deserialize: deserializeBan
+    });
+  }, {after: 'models'});
 } (Misago.prototype));
 } (Misago.prototype));

+ 14 - 0
misago/frontend/misago/models/legal-page.js

@@ -0,0 +1,14 @@
+(function (Misago) {
+  'use strict';
+
+  var LegalPage = function(data) {
+    this.title = data.title;
+    this.body = data.body;
+  };
+
+  Misago.addService('legal-page-model', function(_) {
+    _.models.add('legal-page', {
+      class: LegalPage
+    });
+  }, {after: 'models'});
+} (Misago.prototype));

+ 7 - 6
misago/frontend/misago/routes/legal.js

@@ -15,26 +15,27 @@
         }
         }
       },
       },
       vm: {
       vm: {
+        page: null,
         isReady: false,
         isReady: false,
         init: function(component, _) {
         init: function(component, _) {
           if (this.isReady) {
           if (this.isReady) {
             _.title.set(this.title);
             _.title.set(this.title);
           } else {
           } else {
             _.title.set();
             _.title.set();
-            return _.api.one('legal-pages', dashedTypeName);
+            return _.api.one('legal-page', dashedTypeName);
           }
           }
         },
         },
         ondata: function(data, component, _) {
         ondata: function(data, component, _) {
           m.startComputation();
           m.startComputation();
 
 
-          this.title = data.title || defaultTitle;
-          this.body = data.body;
+          data.title = data.title || defaultTitle;
+          this.page = _.models.deserialize('legal-page', data);
           this.isReady = true;
           this.isReady = true;
 
 
           m.endComputation();
           m.endComputation();
 
 
           if (component.isActive) {
           if (component.isActive) {
-            _.title.set(data.title);
+            _.title.set(this.page.title);
           }
           }
         }
         }
       },
       },
@@ -42,9 +43,9 @@
         var _ = this.container;
         var _ = this.container;
 
 
         return m('.page.legal-page.' + dashedTypeName + '-page', [
         return m('.page.legal-page.' + dashedTypeName + '-page', [
-          _.component(Misago.PageHeader, {title: this.vm.title}),
+          _.component(Misago.PageHeader, {title: this.vm.page.title}),
           m('.container',
           m('.container',
-            _.component(Misago.Markup, Misago.this.vm.body)
+            _.component(Misago.Markup, this.vm.page.body)
           )
           )
         ]);
         ]);
       }
       }

+ 6 - 6
misago/frontend/misago/services/ajax.js

@@ -75,16 +75,16 @@
       }
       }
     };
     };
 
 
-    this.post = function(url) {
-      return this.ajax('POST', url);
+    this.post = function(url, data) {
+      return this.ajax('POST', url, data);
     };
     };
 
 
-    this.patch = function(url) {
-      return this.ajax('PATCH', url);
+    this.patch = function(url, data) {
+      return this.ajax('PATCH', url, data);
     };
     };
 
 
-    this.put = function(url) {
-      return this.ajax('PUT', url);
+    this.put = function(url, data) {
+      return this.ajax('PUT', url, data);
     };
     };
 
 
     this.delete = function(url) {
     this.delete = function(url) {

+ 7 - 1
misago/frontend/misago/services/api.js

@@ -1,9 +1,15 @@
 (function (Misago) {
 (function (Misago) {
   'use strict';
   'use strict';
 
 
+  var Query = function(_, model) {
+
+  };
+
   var Api = function(_) {
   var Api = function(_) {
+    var apiRoot = _.setup.api;
+
     this.buildUrl = function(model, call, querystrings) {
     this.buildUrl = function(model, call, querystrings) {
-      var url = _.router.baseUrl;
+      var url = _.setup.api;
       url += 'api/' + model + '/';
       url += 'api/' + model + '/';
       return url;
       return url;
     };
     };

+ 38 - 0
misago/frontend/misago/services/models.js

@@ -0,0 +1,38 @@
+(function (Misago) {
+  'use strict';
+
+  var Models = function() {
+    this.classes = {};
+    this.deserializers = {};
+
+    this.add = function(name, kwargs) {
+      if (kwargs.class) {
+        this.classes[name] = kwargs.class;
+      }
+
+      if (kwargs.deserialize) {
+        this.deserializers[name] = kwargs.deserialize;
+      }
+    };
+
+    this.new = function(name, data) {
+      if (this.classes[name]) {
+        return new this.classes[name](data);
+      } else {
+        return data;
+      }
+    };
+
+    this.deserialize = function(name, json) {
+      if (this.deserializers[name]) {
+        return this.new(name, this.deserializers[name](json, this));
+      } else {
+        return this.new(name, json);
+      }
+    };
+  };
+
+  Misago.addService('models', function() {
+    return new Models();
+  });
+}(Misago.prototype));

+ 1 - 1
misago/frontend/misago/services/router.js

@@ -118,7 +118,7 @@
         component = routedComponent(Misago.ErrorBannedRoute);
         component = routedComponent(Misago.ErrorBannedRoute);
         component.error = {
         component.error = {
           message: error.detail,
           message: error.detail,
-          ban: Misago.Ban.deserialize(error.ban)
+          ban: _.models.deserialize('ban', error.ban)
         };
         };
       } else {
       } else {
         component = routedComponent(Misago.Error403Route);
         component = routedComponent(Misago.Error403Route);

+ 90 - 3
misago/frontend/test/tests/unit/ajax.js

@@ -8,7 +8,11 @@
   });
   });
 
 
   QUnit.test("service factory", function(assert) {
   QUnit.test("service factory", function(assert) {
-    var container = {context: {CSRF_COOKIE_NAME: 'doesnt-matter'}};
+    var container = {
+      context: {
+        CSRF_COOKIE_NAME: 'doesnt-matter'
+      }
+    };
 
 
     var service = getMisagoService('ajax');
     var service = getMisagoService('ajax');
     var ajax = service(container);
     var ajax = service(container);
@@ -26,7 +30,11 @@
       }
       }
     });
     });
 
 
-    var container = { context: { CSRF_COOKIE_NAME: 'doesnt-matter' } };
+    var container = {
+      context: {
+        CSRF_COOKIE_NAME: 'doesnt-matter'
+      }
+    };
 
 
     var service = getMisagoService('ajax');
     var service = getMisagoService('ajax');
     var ajax = service(container);
     var ajax = service(container);
@@ -48,7 +56,11 @@
       }
       }
     });
     });
 
 
-    var container = { context: { CSRF_COOKIE_NAME: 'doesnt-matter' } };
+    var container = {
+      context: {
+        CSRF_COOKIE_NAME: 'doesnt-matter'
+      }
+    };
 
 
     var service = getMisagoService('ajax');
     var service = getMisagoService('ajax');
     var ajax = service(container);
     var ajax = service(container);
@@ -96,4 +108,79 @@
       });
       });
     });
     });
   });
   });
+
+  QUnit.test("post, patch, put, delete", function(assert) {
+    $.mockjax({
+      type: 'POST',
+      url: '/test-url/',
+      status: 200,
+      responseText: {
+        'detail': 'posted'
+      }
+    });
+
+    $.mockjax({
+      type: 'PATCH',
+      url: '/test-url/',
+      status: 200,
+      responseText: {
+        'detail': 'patched'
+      }
+    });
+
+    $.mockjax({
+      type: 'PUT',
+      url: '/test-url/',
+      status: 200,
+      responseText: {
+        'detail': 'put'
+      }
+    });
+
+    $.mockjax({
+      type: 'DELETE',
+      url: '/test-url/',
+      status: 200,
+      responseText: {
+        'detail': 'deleted'
+      }
+    });
+
+    var container = {
+      context: {
+        CSRF_COOKIE_NAME: 'doesnt-matter',
+        '/test-url/': {
+          'detail': 'preloaded'
+        }
+      }
+    };
+
+    var service = getMisagoService('ajax');
+    var ajax = service(container);
+
+    var donePost = assert.async();
+    var donePatch = assert.async();
+    var donePut = assert.async();
+    var doneDelete = assert.async();
+
+    ajax.post('/test-url/', {}).then(function(data) {
+      assert.equal(data.detail, 'posted', 'post() call succeeded');
+      donePost();
+    });
+
+    ajax.patch('/test-url/', {}).then(function(data) {
+      assert.equal(data.detail, 'patched', 'patch() call succeeded');
+      donePatch();
+    });
+
+    ajax.put('/test-url/', {}).then(function(data) {
+      assert.equal(data.detail, 'put', 'put() call succeeded');
+      donePut();
+    });
+
+    ajax.delete('/test-url/').then(function(data) {
+      assert.equal(data.detail, 'deleted', 'delete() call succeeded');
+      doneDelete();
+    });
+  });
 }());
 }());

+ 92 - 0
misago/frontend/test/tests/unit/models.js

@@ -0,0 +1,92 @@
+(function (Misago) {
+  'use strict';
+
+  QUnit.module("Models");
+
+  QUnit.test("service factory", function(assert) {
+    var container = {};
+
+    var service = getMisagoService('models');
+    var models = service(container);
+
+    assert.ok(models,
+      "service factory has returned service instance.");
+  });
+
+  QUnit.test("add", function(assert) {
+    var container = {};
+
+    var service = getMisagoService('models');
+    var models = service(container);
+
+    var TestModel = function(data) {
+      this.name = data.name || 'Hello';
+    };
+
+    var testModelDeserializer = function(data, models) {
+      return data;
+    };
+
+    models.add('test-model', {
+      class: TestModel,
+      deserialize: testModelDeserializer
+    });
+
+    assert.equal(models.classes['test-model'], TestModel,
+      "test model's class was registered in the service");
+    assert.equal(models.deserializers['test-model'], testModelDeserializer,
+      "test model's deserializer was registered in the service");
+  });
+
+  QUnit.test("new", function(assert) {
+    var container = {};
+
+    var service = getMisagoService('models');
+    var models = service(container);
+
+    var TestModel = function(data) {
+      this.name = data.name || 'Hello';
+    };
+
+    models.add('test-model', {
+      class: TestModel
+    });
+
+    var model = models.new('test-model', {name: 'Working!!!'});
+    assert.equal(model.name, 'Working!!!',
+      "new() returned model instance");
+  });
+
+  QUnit.test("deserialize", function(assert) {
+    var container = {};
+
+    var service = getMisagoService('models');
+    var models = service(container);
+
+    var TestModel = function(data) {
+      this.name = data.name;
+    };
+
+    var testModelDeserializer = function(data, models) {
+      data.name = data.title;
+      return data;
+    };
+
+    models.add('test-model', {
+      class: TestModel,
+      deserialize: testModelDeserializer
+    });
+
+    var model = models.deserialize('test-model', {title: 'Testing!'});
+    assert.equal(model.name, 'Testing!',
+      "deserialize() returned deserialized model instance");
+
+    models.add('other-model', {
+      class: TestModel
+    });
+
+    model = models.deserialize('other-model', {name: 'Other!'});
+    assert.equal(model.name, 'Other!',
+      "deserialize() returned model instance without deserialization");
+  });
+}(Misago.prototype));