0 Votes

Changes for page Todolist Macro

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

From version 12.1
edited by Ryan C
on 2025/04/24 11:07
Change comment: Todo List item added
To version 9.1
edited by Ryan C
on 2025/04/24 10:29
Change comment: There is no comment for this version

Summary

Details

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