0 Votes

Changes for page Todolist Macro

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

From version 27.1
edited by Ryan C
on 2025/04/24 11:25
Change comment: There is no comment for this version
To version 26.1
edited by Ryan C
on 2025/04/24 11:19
Change comment: There is no comment for this version

Summary

Details

XWiki.JavaScriptExtension[0]
Code
... ... @@ -1,13 +1,8 @@
1 1  requirejs.config({
2 2   baseUrl: '${xwiki.getDocument("TodoLists.TodoListMacro").getURL("download")}/',
3 3   paths: {
4 - // Use existing jQuery if available, otherwise load 1.10.2
5 - 'jquery': window.jQuery ? 'empty:' : 'https://code.jquery.com/jquery-1.10.2.min'
4 + 'jquery': 'https://code.jquery.com/jquery-3.6.0.min' // Updated jQuery version
6 6   },
7 - map: {
8 - // Map any module requiring 'jquery' to use the global jQuery
9 - '*': { 'jquery': window.jQuery ? 'jquery-global' : 'jquery' }
10 - },
11 11   shim: {
12 12   'ember-data': {
13 13   deps: ['ember', 'jquery']
... ... @@ -18,331 +18,290 @@
18 18   }
19 19  });
20 20  
21 -// Define a module that returns the global jQuery
22 -define('jquery-global', [], function() {
23 - return window.jQuery;
24 -});
25 -
26 -// Define empty module for when jQuery is already loaded
27 -define('empty:', [], function() {
28 - return window.jQuery;
29 -});
30 -
31 31  require(['jquery', 'handlebars-v1.2.1', 'ember-data', 'ember'], function($) {
32 - // Check jQuery version compatibility with Ember
33 - var jQueryVersion = $.fn.jquery.split('.');
34 - var majorVersion = parseInt(jQueryVersion[0]);
35 - var minorVersion = parseInt(jQueryVersion[1]);
17 + // Create app
18 + window.Todos = Ember.Application.create({
19 + rootElement: '#todoappdiv'
20 + });
36 36  
37 - console.log("Using jQuery version:", $.fn.jquery);
38 -
39 - // Verify jQuery version is compatible with Ember
40 - var isCompatible = (majorVersion === 1 && minorVersion >= 7 && minorVersion <= 10) ||
41 - (majorVersion === 2 && minorVersion === 0);
42 -
43 - if (!isCompatible) {
44 - console.error("Warning: Ember Views require jQuery 1.7, 1.8, 1.9, 1.10, or 2.0. Current version:", $.fn.jquery);
45 - // Try to load a compatible version if needed
46 - require(['https://code.jquery.com/jquery-1.10.2.min.js'], function(compatibleJQuery) {
47 - // Store the original jQuery
48 - var originalJQuery = window.jQuery;
49 - // Replace with compatible jQuery temporarily
50 - window.jQuery = compatibleJQuery;
51 - // Continue with the rest of the code
52 - initializeEmberApp(compatibleJQuery);
53 - // Restore original jQuery when done
54 - window.jQuery = originalJQuery;
55 - });
56 - } else {
57 - // jQuery version is compatible, proceed normally
58 - initializeEmberApp($);
59 - }
60 -
61 - function initializeEmberApp($) {
62 - // Create app
63 - window.Todos = Ember.Application.create({
64 - rootElement: '#todoappdiv'
65 - });
66 -
67 - // Define the todolist store that will write to the TodoListsService
68 - Todos.ApplicationAdapter = DS.Adapter.extend({
69 - namespace: 'api', // Moved inside the adapter definition
70 -
71 - createRecord: function(store, type, record) {
72 - console.log("createRecord");
73 - var data = this.serialize(record, { includeId: true });
74 - var query = { create: "1", content: JSON.stringify(data) };
75 -
76 - return new Ember.RSVP.Promise(function(resolve, reject) {
77 - var url = "${xwiki.getURL('TodoLists.TodoListsService')}?page=" +
78 - XWiki.currentSpace + "." + XWiki.currentPage +
79 - "&xpage=plain&outputSyntax=plain";
80 - console.log("Creating record, URL:", url);
81 -
82 - jQuery.getJSON(url, query).then(function(data) {
83 - console.log("Create success:", data);
84 - Ember.run(function() {
85 - resolve(data);
86 - });
87 - }, function(jqXHR) {
88 - console.error("Create error:", jqXHR);
89 - Ember.run(function() {
90 - reject(jqXHR);
91 - });
22 + // Define the todolist store that will write to the TodoListsService
23 + Todos.ApplicationAdapter = DS.Adapter.extend({
24 + namespace: 'api', // Moved inside the adapter definition
25 +
26 + createRecord: function(store, type, record) {
27 + console.log("createRecord");
28 + var data = this.serialize(record, { includeId: true });
29 + var query = { create: "1", content: JSON.stringify(data) };
30 +
31 + return new Ember.RSVP.Promise(function(resolve, reject) {
32 + var url = "${xwiki.getURL('TodoLists.TodoListsService')}?page=" +
33 + XWiki.currentSpace + "." + XWiki.currentPage +
34 + "&xpage=plain&outputSyntax=plain";
35 + console.log("Creating record, URL:", url);
36 +
37 + jQuery.getJSON(url, query).then(function(data) {
38 + console.log("Create success:", data);
39 + Ember.run(function() {
40 + resolve(data);
92 92   });
93 - });
94 - },
95 -
96 - deleteRecord: function(store, type, record) {
97 - console.log("deleteRecord");
98 - var recordArrays = store.recordArrayManager.recordArraysForRecord(record);
99 - if (recordArrays && recordArrays.list && recordArrays.list[0]) {
100 - return this.saveAll(recordArrays.list[0].content);
101 - }
102 - return Ember.RSVP.resolve();
103 - },
104 -
105 - find: function(store, type, id) {
106 - console.log("find");
107 - return Ember.RSVP.resolve();
108 - },
109 -
110 - findAll: function(store, type, sinceToken) {
111 - console.log("findAll");
112 - var query = { since: sinceToken };
113 -
114 - return new Ember.RSVP.Promise(function(resolve, reject) {
115 - var url = "${xwiki.getURL('TodoLists.TodoListsService')}?page=" +
116 - XWiki.currentSpace + "." + XWiki.currentPage +
117 - "&xpage=plain&outputSyntax=plain";
118 - console.log("Finding all records, URL:", url);
119 -
120 - jQuery.getJSON(url, query).then(function(data) {
121 - console.log("FindAll success:", data);
122 - Ember.run(function() {
123 - resolve(data);
124 - });
125 - }, function(jqXHR) {
126 - console.error("FindAll error:", jqXHR);
127 - Ember.run(function() {
128 - reject(jqXHR);
129 - });
42 + }, function(jqXHR) {
43 + console.error("Create error:", jqXHR);
44 + Ember.run(function() {
45 + reject(jqXHR);
130 130   });
131 131   });
132 - },
133 -
134 - updateRecord: function(store, type, record) {
135 - console.log("updateRecord");
136 - var recordArrays = store.recordArrayManager.recordArraysForRecord(record);
137 - if (recordArrays && recordArrays.list && recordArrays.list[0]) {
138 - return this.saveAll(recordArrays.list[0].content);
139 - }
140 - return Ember.RSVP.resolve();
141 - },
142 -
143 - saveAll: function(alldata) {
144 - console.log("saveAll");
145 - var query = { save: "1", content: JSON.stringify(alldata) };
146 -
147 - return new Ember.RSVP.Promise(function(resolve, reject) {
148 - var currentPage = XWiki.currentSpace + "." + XWiki.currentPage;
149 - var url = "${xwiki.getURL('TodoLists.TodoListsService')}?page=" +
150 - currentPage + "&xpage=plain&outputSyntax=plain";
151 - console.log("Saving all records, URL:", url, "Page:", currentPage);
152 -
153 - jQuery.getJSON(url, query).then(function(data) {
154 - console.log("SaveAll success:", data);
155 - Ember.run(function() {
156 - resolve(data);
157 - });
158 - }, function(jqXHR) {
159 - console.error("SaveAll error:", jqXHR);
160 - Ember.run(function() {
161 - reject(jqXHR);
162 - });
48 + });
49 + },
50 +
51 + deleteRecord: function(store, type, record) {
52 + console.log("deleteRecord");
53 + var recordArrays = store.recordArrayManager.recordArraysForRecord(record);
54 + if (recordArrays && recordArrays.list && recordArrays.list[0]) {
55 + return this.saveAll(recordArrays.list[0].content);
56 + }
57 + return Ember.RSVP.resolve();
58 + },
59 +
60 + find: function(store, type, id) {
61 + console.log("find");
62 + return Ember.RSVP.resolve();
63 + },
64 +
65 + findAll: function(store, type, sinceToken) {
66 + console.log("findAll");
67 + var query = { since: sinceToken };
68 +
69 + return new Ember.RSVP.Promise(function(resolve, reject) {
70 + var url = "${xwiki.getURL('TodoLists.TodoListsService')}?page=" +
71 + XWiki.currentSpace + "." + XWiki.currentPage +
72 + "&xpage=plain&outputSyntax=plain";
73 + console.log("Finding all records, URL:", url);
74 +
75 + jQuery.getJSON(url, query).then(function(data) {
76 + console.log("FindAll success:", data);
77 + Ember.run(function() {
78 + resolve(data);
163 163   });
80 + }, function(jqXHR) {
81 + console.error("FindAll error:", jqXHR);
82 + Ember.run(function() {
83 + reject(jqXHR);
84 + });
164 164   });
86 + });
87 + },
88 +
89 + updateRecord: function(store, type, record) {
90 + console.log("updateRecord");
91 + var recordArrays = store.recordArrayManager.recordArraysForRecord(record);
92 + if (recordArrays && recordArrays.list && recordArrays.list[0]) {
93 + return this.saveAll(recordArrays.list[0].content);
165 165   }
166 - });
167 -
168 - // Routing
169 - Todos.Router.map(function() {
170 - this.resource('todos', { path: '' }, function() {
171 - this.route('active');
172 - this.route('completed');
95 + return Ember.RSVP.resolve();
96 + },
97 +
98 + saveAll: function(alldata) {
99 + console.log("saveAll");
100 + var query = { save: "1", content: JSON.stringify(alldata) };
101 +
102 + return new Ember.RSVP.Promise(function(resolve, reject) {
103 + var currentPage = XWiki.currentSpace + "." + XWiki.currentPage;
104 + var url = "${xwiki.getURL('TodoLists.TodoListsService')}?page=" +
105 + currentPage + "&xpage=plain&outputSyntax=plain";
106 + console.log("Saving all records, URL:", url, "Page:", currentPage);
107 +
108 + jQuery.getJSON(url, query).then(function(data) {
109 + console.log("SaveAll success:", data);
110 + Ember.run(function() {
111 + resolve(data);
112 + });
113 + }, function(jqXHR) {
114 + console.error("SaveAll error:", jqXHR);
115 + Ember.run(function() {
116 + reject(jqXHR);
117 + });
118 + });
173 173   });
174 - });
120 + }
121 + });
175 175  
176 - Todos.TodosRoute = Ember.Route.extend({
177 - model: function() {
178 - return this.store.find('todo');
179 - }
123 + // Routing
124 + Todos.Router.map(function() {
125 + this.resource('todos', { path: '' }, function() {
126 + this.route('active');
127 + this.route('completed');
180 180   });
129 + });
181 181  
182 - Todos.TodosIndexRoute = Ember.Route.extend({
183 - model: function() {
184 - return this.modelFor('todos');
185 - }
186 - });
131 + Todos.TodosRoute = Ember.Route.extend({
132 + model: function() {
133 + return this.store.find('todo');
134 + }
135 + });
187 187  
188 - Todos.TodosActiveRoute = Ember.Route.extend({
189 - model: function() {
190 - return this.store.filter('todo', function(todo) {
191 - return !todo.get('isCompleted');
192 - });
193 - },
194 - renderTemplate: function(controller) {
195 - this.render('todos/index', { controller: controller });
196 - }
197 - });
137 + Todos.TodosIndexRoute = Ember.Route.extend({
138 + model: function() {
139 + return this.modelFor('todos');
140 + }
141 + });
198 198  
199 - Todos.TodosCompletedRoute = Ember.Route.extend({
200 - model: function() {
201 - return this.store.filter('todo', function(todo) {
202 - return todo.get('isCompleted');
203 - });
204 - },
205 - renderTemplate: function(controller) {
206 - this.render('todos/index', { controller: controller });
207 - }
208 - });
143 + Todos.TodosActiveRoute = Ember.Route.extend({
144 + model: function() {
145 + return this.store.filter('todo', function(todo) {
146 + return !todo.get('isCompleted');
147 + });
148 + },
149 + renderTemplate: function(controller) {
150 + this.render('todos/index', { controller: controller });
151 + }
152 + });
209 209  
210 - // Data model
211 - Todos.Todo = DS.Model.extend({
212 - title: DS.attr('string'),
213 - priority: DS.attr('string'),
214 - assignee: DS.attr('string'),
215 - isCompleted: DS.attr('boolean')
216 - });
154 + Todos.TodosCompletedRoute = Ember.Route.extend({
155 + model: function() {
156 + return this.store.filter('todo', function(todo) {
157 + return todo.get('isCompleted');
158 + });
159 + },
160 + renderTemplate: function(controller) {
161 + this.render('todos/index', { controller: controller });
162 + }
163 + });
217 217  
218 - // Controller
219 - Todos.TodoController = Ember.ObjectController.extend({
220 - actions: {
221 - editTodo: function() {
222 - this.set('isEditing', true);
223 - },
224 - acceptChanges: function() {
225 - this.set('isEditing', false);
165 + // Data model
166 + Todos.Todo = DS.Model.extend({
167 + title: DS.attr('string'),
168 + priority: DS.attr('string'),
169 + assignee: DS.attr('string'),
170 + isCompleted: DS.attr('boolean')
171 + });
226 226  
227 - if (Ember.isEmpty(this.get('model.title'))) {
228 - this.send('removeTodo');
229 - } else {
230 - this.get('model').save();
231 - }
232 - },
233 - removeTodo: function() {
234 - var todo = this.get('model');
235 - todo.deleteRecord();
236 - todo.save();
237 - }
173 + // Controller
174 + Todos.TodoController = Ember.ObjectController.extend({
175 + actions: {
176 + editTodo: function() {
177 + this.set('isEditing', true);
238 238   },
179 + acceptChanges: function() {
180 + this.set('isEditing', false);
239 239  
240 - isEditing: false,
241 -
242 - isCompleted: function(key, value) {
243 - var model = this.get('model');
244 -
245 - if (value === undefined) {
246 - // Property being used as a getter
247 - return model.get('isCompleted');
182 + if (Ember.isEmpty(this.get('model.title'))) {
183 + this.send('removeTodo');
248 248   } else {
249 - // Property being used as setter
250 - model.set('isCompleted', value);
251 - model.save();
252 - return value;
185 + this.get('model').save();
253 253   }
254 - }.property('model.isCompleted')
255 - });
187 + },
188 + removeTodo: function() {
189 + var todo = this.get('model');
190 + todo.deleteRecord();
191 + todo.save();
192 + }
193 + },
256 256  
257 - Todos.TodosController = Ember.ArrayController.extend({
258 - actions: {
259 - createTodo: function() {
260 - // Get the todo title set by the "New Todo" text field
261 - var title = this.get('newTitle');
262 - if (!title || !title.trim()) { return; }
195 + isEditing: false,
263 263  
264 - console.log("Creating new todo with title:", title);
197 + isCompleted: function(key, value) {
198 + var model = this.get('model');
265 265  
266 - // Create the new Todo model
267 - var todo = this.store.createRecord('todo', {
268 - title: title,
269 - priority: "P3",
270 - assignee: "all",
271 - isCompleted: false
272 - });
200 + if (value === undefined) {
201 + // Property being used as a getter
202 + return model.get('isCompleted');
203 + } else {
204 + // Property being used as setter
205 + model.set('isCompleted', value);
206 + model.save();
207 + return value;
208 + }
209 + }.property('model.isCompleted')
210 + });
273 273  
274 - // Clear the "New Todo" text field
275 - this.set('newTitle', '');
212 + Todos.TodosController = Ember.ArrayController.extend({
213 + actions: {
214 + createTodo: function() {
215 + // Get the todo title set by the "New Todo" text field
216 + var title = this.get('newTitle');
217 + if (!title || !title.trim()) { return; }
276 276  
277 - // Save the new model
278 - todo.save().then(function(savedTodo) {
279 - console.log("Todo saved successfully:", savedTodo);
280 - // Force a refresh of the list after saving
281 - Ember.run.later(function() {
282 - console.log("Refreshing todo list");
283 - Todos.store.find('todo');
284 - }, 100);
285 - }, function(error) {
286 - console.error("Failed to save todo:", error);
287 - });
288 - },
219 + console.log("Creating new todo with title:", title);
289 289  
290 - clearCompleted: function() {
291 - var completed = this.filter(function(todo) {
292 - return todo.get('isCompleted');
293 - });
221 + // Create the new Todo model
222 + var todo = this.store.createRecord('todo', {
223 + title: title,
224 + priority: "P3",
225 + assignee: "all",
226 + isCompleted: false
227 + });
294 294  
295 - completed.forEach(function(todo) {
296 - todo.deleteRecord();
297 - todo.save();
298 - });
299 - }
229 + // Clear the "New Todo" text field
230 + this.set('newTitle', '');
231 +
232 + // Save the new model
233 + todo.save().then(function(savedTodo) {
234 + console.log("Todo saved successfully:", savedTodo);
235 + // Force a refresh of the list after saving
236 + Ember.run.later(function() {
237 + console.log("Refreshing todo list");
238 + Todos.store.find('todo');
239 + }, 100);
240 + }, function(error) {
241 + console.error("Failed to save todo:", error);
242 + });
300 300   },
244 +
245 + clearCompleted: function() {
246 + var completed = this.filter(function(todo) {
247 + return todo.get('isCompleted');
248 + });
249 +
250 + completed.forEach(function(todo) {
251 + todo.deleteRecord();
252 + todo.save();
253 + });
254 + }
255 + },
301 301  
302 - remaining: function() {
303 - return this.filter(function(todo) {
304 - return !todo.get('isCompleted');
305 - }).get('length');
306 - }.property('@each.isCompleted'),
257 + remaining: function() {
258 + return this.filter(function(todo) {
259 + return !todo.get('isCompleted');
260 + }).get('length');
261 + }.property('@each.isCompleted'),
307 307  
308 - inflection: function() {
309 - var remaining = this.get('remaining');
310 - return remaining === 1 ? 'item' : 'items';
311 - }.property('remaining'),
263 + inflection: function() {
264 + var remaining = this.get('remaining');
265 + return remaining === 1 ? 'item' : 'items';
266 + }.property('remaining'),
267 +
268 + hasCompleted: function() {
269 + return this.get('completed') > 0;
270 + }.property('completed'),
312 312  
313 - hasCompleted: function() {
314 - return this.get('completed') > 0;
315 - }.property('completed'),
272 + completed: function() {
273 + return this.filter(function(todo) {
274 + return todo.get('isCompleted');
275 + }).get('length');
276 + }.property('@each.isCompleted'),
316 316  
317 - completed: function() {
318 - return this.filter(function(todo) {
278 + allAreDone: function(key, value) {
279 + if (value === undefined) {
280 + return this.get('length') > 0 && this.every(function(todo) {
319 319   return todo.get('isCompleted');
320 - }).get('length');
321 - }.property('@each.isCompleted'),
322 -
323 - allAreDone: function(key, value) {
324 - if (value === undefined) {
325 - return this.get('length') > 0 && this.every(function(todo) {
326 - return todo.get('isCompleted');
327 - });
328 - } else {
329 - this.forEach(function(todo) {
330 - todo.set('isCompleted', value);
331 - todo.save();
332 - });
333 - return value;
334 - }
335 - }.property('@each.isCompleted')
336 - });
337 -
338 - // Editing
339 - Todos.EditTodoView = Ember.TextField.extend({
340 - didInsertElement: function() {
341 - this.$().focus();
282 + });
283 + } else {
284 + this.forEach(function(todo) {
285 + todo.set('isCompleted', value);
286 + todo.save();
287 + });
288 + return value;
342 342   }
343 - });
290 + }.property('@each.isCompleted')
291 + });
344 344  
345 - Ember.Handlebars.helper('edit-todo', Todos.EditTodoView);
346 - }
293 + // Editing
294 + Todos.EditTodoView = Ember.TextField.extend({
295 + didInsertElement: function() {
296 + this.$().focus();
297 + }
298 + });
299 +
300 + Ember.Handlebars.helper('edit-todo', Todos.EditTodoView);
347 347  });
348 348