0 Votes

Changes for page Todolist Macro

Last modified by Ryan C on 2025/04/30 07:54

From version 24.1
edited by Ryan C
on 2025/04/24 11:16
Change comment: There is no comment for this version
To version 10.1
edited by Ryan C
on 2025/04/24 11:00
Change comment: There is no comment for this version

Summary

Details

Page properties
Content
... ... @@ -1,9 +1,7 @@
1 1  Macro to display todo-lists using emberjs. This code is based on the emberjs demo. You can see an example below
2 2  
3 3  {{todolist width="50%" center="1"}}
4 -a 3nd thing|0
5 -adding this thing|0
6 -adding this thing|0
7 -refreshed they are still there not even having to save page|0
4 +a thing|1
5 +a second thing|0
8 8  
9 9  {{/todolist}}
XWiki.JavaScriptExtension[0]
Code
... ... @@ -1,7 +1,7 @@
1 1  requirejs.config({
2 2   baseUrl: '${xwiki.getDocument("TodoLists.TodoListMacro").getURL("download")}/',
3 3   paths: {
4 - 'jquery': 'https://code.jquery.com/jquery-3.6.0.min' // Updated jQuery version
4 + 'jquery': 'https://code.jquery.com/jquery-1.10.2.min'
5 5   },
6 6   shim: {
7 7   'ember-data': {
... ... @@ -13,283 +13,241 @@
13 13   }
14 14  });
15 15  
16 -require(['jquery', 'handlebars-v1.2.1', 'ember-data', 'ember'], function($) {
17 - // Create app
18 - window.Todos = Ember.Application.create({
19 - rootElement: '#todoappdiv'
20 - });
16 +require(['jquery', 'handlebars-v1.2.1', 'ember-data', 'ember' ], function ($) {
21 21  
22 - // Define the todolist store that will write to the TodoListsService
23 - Todos.ApplicationAdapter = DS.Adapter.extend({
24 - createRecord: function(store, type, record) {
25 - console.log("createRecord");
26 - var data = this.serialize(record, { includeId: true });
27 - var query = { create: "1", content: JSON.stringify(data) };
28 -
29 - return new Ember.RSVP.Promise(function(resolve, reject) {
30 - jQuery.getJSON(
31 - "${xwiki.getURL('TodoLists.TodoListsService')}?page=" +
32 - XWiki.currentSpace + "." + XWiki.currentPage +
33 - "&xpage=plain&outputSyntax=plain",
34 - query
35 - ).then(function(data) {
36 - Ember.run(function() {
37 - resolve(data);
38 - });
39 - }, function(jqXHR) {
40 - Ember.run(function() {
41 - reject(jqXHR);
42 - });
43 - });
18 +// create app
19 +window.Todos = Ember.Application.create({
20 + rootElement: '#todoappdiv'
21 +});
22 +
23 +// define the todolist store that will write to the TodoListsService
24 +Todos.ApplicationAdapter = DS.Adapter.extend({
25 + createRecord: function(store, type, record) {
26 + console.log("createRecord");
27 + var query = { create: "1", content : JSON.stringify(record) };
28 + return new Ember.RSVP.Promise(function(resolve, reject) {
29 + jQuery.getJSON("${xwiki.getURL("TodoLists.TodoListsService")}?page=" + XWiki.currentSpace + "." + XWiki.currentPage + "&xpage=plain&outputSyntax=plain", query).then(function(data) {
30 + Ember.run(null, resolve, data);
31 + }, function(jqXHR) {
32 + jqXHR.then = null; // tame jQuery's ill mannered promises
33 + Ember.run(null, reject, jqXHR);
44 44   });
45 - },
46 -
47 - deleteRecord: function(store, type, record) {
48 - console.log("deleteRecord");
49 - var recordArrays = store.recordArrayManager.recordArraysForRecord(record);
50 - if (recordArrays && recordArrays.list && recordArrays.list[0]) {
51 - return this.saveAll(recordArrays.list[0].content);
52 - }
53 - return Ember.RSVP.resolve();
54 - },
55 -
56 - find: function(store, type, id) {
57 - console.log("find");
58 - return Ember.RSVP.resolve();
59 - },
60 -
61 - findAll: function(store, type, sinceToken) {
62 - console.log("findAll");
63 - var query = { since: sinceToken };
64 -
65 - return new Ember.RSVP.Promise(function(resolve, reject) {
66 - jQuery.getJSON(
67 - "${xwiki.getURL('TodoLists.TodoListsService')}?page=" +
68 - XWiki.currentSpace + "." + XWiki.currentPage +
69 - "&xpage=plain&outputSyntax=plain",
70 - query
71 - ).then(function(data) {
72 - Ember.run(function() {
73 - resolve(data);
74 - });
75 - }, function(jqXHR) {
76 - Ember.run(function() {
77 - reject(jqXHR);
78 - });
79 - });
35 + });
36 + },
37 + deleteRecord: function(store, type, record) {
38 + console.log("deleteRecord");
39 + return this.saveAll(store.recordArrayManager.recordArraysForRecord(record).list[0].content);
40 + },
41 + find: function(store, type, id) {
42 + console.log("find");
43 + return;
44 + },
45 + findAll: function(store, type, sinceToken) {
46 + console.log("findAll");
47 + var query = { since: sinceToken };
48 + return new Ember.RSVP.Promise(function(resolve, reject) {
49 + jQuery.getJSON("${xwiki.getURL("TodoLists.TodoListsService")}?page=" + XWiki.currentSpace + "." + XWiki.currentPage + "&xpage=plain&outputSyntax=plain", query).then(function(data) {
50 + Ember.run(null, resolve, data);
51 + }, function(jqXHR) {
52 + jqXHR.then = null; // tame jQuery's ill mannered promises
53 + Ember.run(null, reject, jqXHR);
80 80   });
81 - },
82 -
83 - updateRecord: function(store, type, record) {
84 - var recordArrays = store.recordArrayManager.recordArraysForRecord(record);
85 - if (recordArrays && recordArrays.list && recordArrays.list[0]) {
86 - return this.saveAll(recordArrays.list[0].content);
87 - }
88 - return Ember.RSVP.resolve();
89 - },
90 - saveAll: function(alldata) {
91 - console.log("saveAll");
92 - var query = { save: "1", content: JSON.stringify(alldata) };
93 -return new Ember.RSVP.Promise(function(resolve, reject) {
94 - jQuery.getJSON(
95 - "${xwiki.getURL('TodoLists.TodoListsService')}?page=" +
96 - (
97 - typeof XWiki !== 'undefined' &&
98 - XWiki.currentSpace &&
99 - XWiki.currentPage
100 - ? XWiki.currentSpace + "." + XWiki.currentPage
101 - : document.location.pathname.split('/').pop()
102 - ) +
103 - "&xpage=plain&outputSyntax=plain",
104 - query
105 - ).then(function(data) {
106 - Ember.run(function() {
107 - resolve(data);
108 108   });
109 - }, function(jqXHR) {
110 - Ember.run(function() {
111 - reject(jqXHR);
56 + },
57 + updateRecord: function(store, type, record) {
58 + return this.saveAll(store.recordArrayManager.recordArraysForRecord(record).list[0].content);
59 + },
60 + saveAll: function(alldata) {
61 + console.log("updateRecord");
62 + var query = { save: "1", content : JSON.stringify(alldata) };
63 + return new Ember.RSVP.Promise(function(resolve, reject) {
64 + jQuery.getJSON("${xwiki.getURL("TodoLists.TodoListsService")}?page=" + XWiki.currentSpace + "." + XWiki.currentPage + "&xpage=plain&outputSyntax=plain", query).then(function(data) {
65 + Ember.run(null, resolve, data);
66 + }, function(jqXHR) {
67 + jqXHR.then = null; // tame jQuery's ill mannered promises
68 + Ember.run(null, reject, jqXHR);
69 + });
112 112   });
113 - });
71 + }
114 114  });
115 115  
74 +// use my own store
75 +Todos.store = DS.Store.create({
76 + adapter: 'ApplicationAdapter'
77 +});
116 116  
117 - // Register the adapter
118 - Todos.ApplicationAdapter.reopen({
119 - namespace: 'api'
120 - });
79 +// Todos.ApplicationAdapter = DS.FixtureAdapter.extend();
121 121  
122 - // Routing
123 - Todos.Router.map(function() {
124 - this.resource('todos', { path: '' }, function() {
125 - this.route('active');
126 - this.route('completed');
127 - });
81 +// routing
82 +Todos.Router.map(function() {
83 + this.resource('todos', { path: '' }, function() {
84 + this.route('active');
85 + this.route('completed');
128 128   });
87 +});
129 129  
130 - Todos.TodosRoute = Ember.Route.extend({
131 - model: function() {
132 - return this.store.find('todo');
133 - }
134 - });
89 +Todos.TodosRoute = Ember.Route.extend({
90 + model: function() {
91 + return this.store.find('todo');
92 + }
93 +});
135 135  
136 - Todos.TodosIndexRoute = Ember.Route.extend({
137 - model: function() {
138 - return this.modelFor('todos');
139 - }
140 - });
95 +Todos.TodosIndexRoute = Ember.Route.extend({
96 + model: function() {
97 + return this.modelFor('todos');
98 + }
99 +});
141 141  
142 - Todos.TodosActiveRoute = Ember.Route.extend({
143 - model: function() {
144 - return this.store.filter('todo', function(todo) {
145 - return !todo.get('isCompleted');
146 - });
147 - },
148 - renderTemplate: function(controller) {
149 - this.render('todos/index', { controller: controller });
150 - }
151 - });
101 +// ... additional lines truncated for brevity ...
102 +Todos.TodosActiveRoute = Ember.Route.extend({
103 + model: function(){
104 + return this.store.filter('todo', function(todo) {
105 + return !todo.get('isCompleted');
106 + });
107 + },
108 + renderTemplate: function(controller) {
109 + this.render('todos/index', {controller: controller});
110 + }
111 +});
152 152  
153 - Todos.TodosCompletedRoute = Ember.Route.extend({
154 - model: function() {
155 - return this.store.filter('todo', function(todo) {
156 - return todo.get('isCompleted');
157 - });
158 - },
159 - renderTemplate: function(controller) {
160 - this.render('todos/index', { controller: controller });
161 - }
162 - });
113 +Todos.TodosCompletedRoute = Ember.Route.extend({
114 + model: function(){
115 + return this.store.filter('todo', function (todo) {
116 + return todo.get('isCompleted');
117 + });
118 + },
119 + renderTemplate: function(controller){
120 + this.render('todos/index', {controller: controller});
121 + }
122 +});
163 163  
164 - // Data model
165 - Todos.Todo = DS.Model.extend({
166 - title: DS.attr('string'),
167 - priority: DS.attr('string'),
168 - assignee: DS.attr('string'),
169 - isCompleted: DS.attr('boolean')
170 - });
124 +// data model
125 +Todos.Todo = DS.Model.extend({
126 + title: DS.attr('string'),
127 + priority: DS.attr('string'),
128 + assignee: DS.attr('string'),
129 + isCompleted: DS.attr('boolean')
130 +});
171 171  
172 - // Controller
173 - Todos.TodoController = Ember.ObjectController.extend({
174 - actions: {
175 - editTodo: function() {
176 - this.set('isEditing', true);
177 - },
178 - acceptChanges: function() {
179 - this.set('isEditing', false);
132 +// ... additional lines truncated for brevity ...
133 +Todos.Todo.FIXTURES = [
134 + {
135 + id: 1,
136 + title: 'Learn Ember.js X',
137 + isCompleted: true
138 + },
139 + {
140 + id: 2,
141 + title: '...',
142 + isCompleted: false
143 + },
144 + {
145 + id: 3,
146 + title: 'Profit!',
147 + isCompleted: false
148 + }
149 +];
180 180  
181 - if (Ember.isEmpty(this.get('model.title'))) {
182 - this.send('removeTodo');
183 - } else {
184 - this.get('model').save();
185 - }
186 - },
187 - removeTodo: function() {
188 - var todo = this.get('model');
189 - todo.deleteRecord();
190 - todo.save();
191 - }
151 +// controler
152 +Todos.TodoController = Ember.ObjectController.extend({
153 + actions: {
154 + editTodo: function () {
155 + this.set('isEditing', true);
192 192   },
157 + acceptChanges: function() {
158 + this.set('isEditing', false);
193 193  
194 - isEditing: false,
160 + if (Ember.isEmpty(this.get('model.title'))) {
161 + this.send('removeTodo');
162 + } else {
163 + this.get('model').save();
164 + }
165 + },
166 + removeTodo: function() {
167 + var todo = this.get('model');
168 + todo.deleteRecord();
169 + todo.save();
170 + }
171 + },
195 195  
196 - isCompleted: function(key, value) {
197 - var model = this.get('model');
173 + isEditing: false,
198 198  
199 - if (value === undefined) {
200 - // Property being used as a getter
201 - return model.get('isCompleted');
202 - } else {
203 - // Property being used as setter
204 - model.set('isCompleted', value);
205 - model.save();
206 - return value;
207 - }
208 - }.property('model.isCompleted')
209 - });
175 + isCompleted: function(key, value){
176 + var model = this.get('model');
210 210  
211 - Todos.TodosController = Ember.ArrayController.extend({
212 - actions: {
213 - createTodo: function() {
214 - // Get the todo title set by the "New Todo" text field
215 - var title = this.get('newTitle');
216 - if (!title || !title.trim()) { return; }
178 + if (value === undefined) {
179 + // property being used as a getter
180 + return model.get('isCompleted');
181 + } else {
182 + // property being used as setter
183 + model.set('isCompleted', value);
184 + model.save();
185 + return value;
186 + }
187 + }.property('model.isCompleted')
188 +});
217 217  
218 - // Create the new Todo model
219 - var todo = this.store.createRecord('todo', {
220 - title: title,
221 - priority: "P3",
222 - assignee: "all",
223 - isCompleted: false
224 - });
190 +Todos.TodosController = Ember.ArrayController.extend({
191 + actions: {
192 + createTodo: function () {
193 + // Get the todo title set by the "New Todo" text field
194 + var title = this.get('newTitle');
195 + if (!title.trim()) { return; }
225 225  
226 - // Clear the "New Todo" text field
227 - this.set('newTitle', '');
197 + // Create the new Todo model
198 + var todo = this.store.createRecord('todo', {
199 + title: title,
200 + priority: "P3",
201 + assignee: "all",
202 + isCompleted: false
203 + });
228 228  
229 - // Save the new model
230 - todo.save().then(function() {
231 - // Force a refresh of the list after saving
232 - Ember.run.later(function() {
233 - Todos.store.find('todo');
234 - }, 100);
235 - });
236 - },
237 -
238 - clearCompleted: function() {
239 - var completed = this.filter(function(todo) {
240 - return todo.get('isCompleted');
241 - });
242 -
243 - completed.forEach(function(todo) {
244 - todo.deleteRecord();
245 - todo.save();
246 - });
247 - }
205 + // Clear the "New Todo" text field
206 + this.set('newTitle', '');
207 +
208 + // Save the new model
209 + todo.save();
248 248   },
211 + clearCompleted: function () {
212 + var completed = this.filterProperty('isCompleted', true);
213 + completed.invoke('deleteRecord');
214 + completed.invoke('save');
215 + }
216 + },
249 249  
250 - remaining: function() {
251 - return this.filter(function(todo) {
252 - return !todo.get('isCompleted');
253 - }).get('length');
254 - }.property('@each.isCompleted'),
218 + remaining: function () {
219 + return this.filterProperty('isCompleted', false).get('length');
220 + }.property('@each.isCompleted'),
255 255  
256 - inflection: function() {
257 - var remaining = this.get('remaining');
258 - return remaining === 1 ? 'item' : 'items';
259 - }.property('remaining'),
260 -
261 - hasCompleted: function() {
262 - return this.get('completed') > 0;
263 - }.property('completed'),
222 + inflection: function () {
223 + var remaining = this.get('remaining');
224 + return remaining === 1 ? 'item' : 'items';
225 + }.property('remaining'),
226 + hasCompleted: function () {
227 + return this.get('completed') > 0;
228 + }.property('completed'),
264 264  
265 - completed: function() {
266 - return this.filter(function(todo) {
267 - return todo.get('isCompleted');
268 - }).get('length');
269 - }.property('@each.isCompleted'),
230 + completed: function () {
231 + return this.filterProperty('isCompleted', true).get('length');
232 + }.property('@each.isCompleted'),
270 270  
271 - allAreDone: function(key, value) {
272 - if (value === undefined) {
273 - return this.get('length') > 0 && this.every(function(todo) {
274 - return todo.get('isCompleted');
275 - });
276 - } else {
277 - this.forEach(function(todo) {
278 - todo.set('isCompleted', value);
279 - todo.save();
280 - });
281 - return value;
282 - }
283 - }.property('@each.isCompleted')
284 - });
234 + allAreDone: function(key, value) {
235 + if (value === undefined) {
236 + return !!this.get('length') && this.everyProperty('isCompleted', true);
237 + } else {
238 + this.setEach('isCompleted', value);
239 + this.invoke('save');
240 + return value;
241 + }
242 +}.property('@each.isCompleted')
243 +});
285 285  
286 - // Editing
287 - Todos.EditTodoView = Ember.TextField.extend({
288 - didInsertElement: function() {
289 - this.$().focus();
290 - }
291 - });
292 -
293 - Ember.Handlebars.helper('edit-todo', Todos.EditTodoView);
245 +// editing
246 +Todos.EditTodoView = Ember.TextField.extend({
247 + didInsertElement: function() {
248 + this.$().focus();
249 + }
294 294  });
295 295  
252 +Ember.Handlebars.helper('edit-todo', Todos.EditTodoView);
253 +});