Skip to content

Commit e148ebe

Browse files
committed
added Kanban-style states to to-do list (open, in-progress, done)
and improved code modularity
1 parent 4d5c65d commit e148ebe

File tree

4 files changed

+129
-48
lines changed

4 files changed

+129
-48
lines changed

www/css/sepiaFW-cards.css

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
font-weight: bold;
9292
line-height: 27px;
9393
}
94-
.sepiaFW-cards-list-title span {
94+
.sepiaFW-cards-list-title > span {
9595
/*position: absolute;
9696
left: 50%;
9797
top: 50%;
@@ -204,6 +204,7 @@
204204
/*border-right: 3px solid #e5e5e5;*/
205205
margin: 0px 3px 0px 5px;
206206
user-select: none;
207+
cursor: pointer;
207208
}
208209
.sepiaFW-cards-list-body .listElement .listCenter {
209210
display: flex;
@@ -233,15 +234,18 @@
233234
.sepiaFW-cards-list-body .listElement .checked {
234235
background: rgba(0, 255, 0, 0.50);
235236
}
236-
.sepiaFW-notouch-device .sepiaFW-cards-list-body .listElement .checked:hover {
237-
background: rgba(0, 255, 255, 0.50);
237+
.sepiaFW-cards-list-body .listElement .inProgress {
238+
background: rgba(255, 255, 0, 0.50);
238239
}
239-
.sepiaFW-cards-list-body .listElement .unchecked {
240-
/*background: rgba(255, 255, 255, 0.90);*/
241-
}
242-
.sepiaFW-notouch-device .sepiaFW-cards-list-body .listElement .unchecked:hover {
240+
/*.sepiaFW-cards-list-body .listElement .unchecked {
241+
background: rgba(255, 255, 255, 0.90);
242+
}*/
243+
/*.sepiaFW-notouch-device .sepiaFW-cards-list-body .listElement .unchecked:hover {
243244
background: rgba(0, 255, 0, 0.50);
244245
}
246+
.sepiaFW-notouch-device .sepiaFW-cards-list-body .listElement .checked:hover {
247+
background: rgba(0, 255, 255, 0.50);
248+
}*/
245249

246250
/* hidden and visible */
247251
.sepiaFW-cards-list-body .itemHidden {
@@ -376,13 +380,14 @@
376380
cursor: pointer;
377381
padding: 5px;
378382
}
379-
.sepiaFW-notouch-device .sepiaFW-cards-list-body .timeEvent .timeEventRight:hover { background: rgba(255, 0, 0, 0.50); }
383+
.sepiaFW-notouch-device .sepiaFW-cards-list-body .timeEvent .timeEventRight:hover { background: rgba(255, 0, 0, 0.50); }
380384

381385
/* ---- News ---- */
382386

383387
.sepiaFW-cards-list-title.newsHeader {
384388
background: rgba(255, 255, 255, 0.90);
385-
border-radius: 0;
389+
border-radius: 0;
390+
font-weight: normal;
386391
}
387392
.sepiaFW-cards-list-title.newsHeader span {
388393
padding-left: 0px;

www/css/sepiaFW-frames.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@
6060
/*overflow-y: overlay;*/
6161
-webkit-overflow-scrolling: touch;
6262
}
63+
.sepiaFW-frames-page a {
64+
color: #4ec48f;
65+
}
66+
.sepiaFW-frames-page a:visited {
67+
color: #4ec48f;
68+
}
6369
.sepiaFW-frames-page button {
6470
background: #000 !important;
6571
color: #ceff1a !important;

www/scripts/sepiaFW.ui.cards.js

Lines changed: 108 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -185,12 +185,42 @@ function sepiaFW_build_ui_cards(){
185185

186186
//USER DATA LIST
187187

188+
var INDEX_TYPE_TODO = "todo";
189+
var INDEX_TYPE_SHOPPING = "shopping";
190+
var INDEX_TYPE_REMINDERS = "reminders";
191+
var INDEX_TYPE_APPOINTMENTS = "appointments";
192+
var INDEX_TYPE_ALARMS = "alarms"; //includes timers
193+
var INDEX_TYPE_NEWS_FAVORITES = "newsFavorites";
194+
var INDEX_TYPE_UNKNOWN = "unknown";
195+
188196
//Default sort-drag-options
189197
var udListCheckablesDragOptions = {
190198
allowCrossContainerDrag: true,
191199
activateDragAfterLongPress: true,
192200
autoDisableAfterDrop: true,
193201
};
202+
203+
//Make an empty list object for a certain list type
204+
function makeProductivityListObject(name, indexType){
205+
var emptyItemData;
206+
if (indexType === INDEX_TYPE_TODO){
207+
//To-Do
208+
emptyItemData = {
209+
'name' : name,
210+
'checked' : false,
211+
'state' : 'open',
212+
'dateAdded' : (new Date().getTime())
213+
};
214+
}else{
215+
//Shopping
216+
emptyItemData = {
217+
'name' : name,
218+
'checked' : false,
219+
'dateAdded' : (new Date().getTime())
220+
};
221+
}
222+
return emptyItemData;
223+
}
194224

195225
//UserDataList
196226
function makeUserDataList(user, sectionName, indexType, title, data, _id){
@@ -214,6 +244,7 @@ function sepiaFW_build_ui_cards(){
214244

215245
return list;
216246
}
247+
217248
//build card of this type
218249
function buildUserDataList(cardElementInfo){
219250
var newId = ("sepiaFW-card-id-" + Cards.currentCardId++);
@@ -227,7 +258,7 @@ function sepiaFW_build_ui_cards(){
227258

228259
var indexType = cardElementInfo.indexType;
229260
var titleName = cardElementInfo.title;
230-
var isTimerAndAlarmsList = (indexType === "alarms"); //Note: section === "timeEvents" might even be better here
261+
var isTimerAndAlarmsList = (indexType === INDEX_TYPE_ALARMS); //Note: section === "timeEvents" might even be better here
231262
if (isTimerAndAlarmsList){
232263
sortData = true; //NOTE: maybe we should read this value from the list info itself ... maybe it is already sorted ...
233264

@@ -255,6 +286,7 @@ function sepiaFW_build_ui_cards(){
255286

256287
//list elements
257288
var cardBody = document.createElement('DIV');
289+
cardBody.className = "sepiaFW-cards-list-body";
258290
var maxShow = 4;
259291
var N = elementsData.length;
260292
var hasTimer=0, hasAlarm=0, hasCheckable=0;
@@ -280,7 +312,7 @@ function sepiaFW_build_ui_cards(){
280312

281313
//default: checkable element (default list element)
282314
}else{
283-
var listEle = makeUserDataListElement(elementsData[i]);
315+
var listEle = makeUserDataListElement(elementsData[i], cardElementInfo);
284316
cardBody.appendChild(listEle);
285317
if (hasCheckable === 0) { hasCheckable = 1; cardBody.className = "sepiaFW-cards-list-body sepiaFW-cards-list-checkables"; }
286318
setupUserDataListElementButtons(listEle); //we do this as last step, after classes are set and ele ist appended!
@@ -292,7 +324,7 @@ function sepiaFW_build_ui_cards(){
292324
//refresh background notifications
293325
//is mixed result?
294326
if ((hasTimer + hasAlarm + hasCheckable) > 1){
295-
cardBody.className = "sepiaFW-cards-list-body sepiaFW-cards-list-mixed"; //overwrite class - mixed card body
327+
cardBody.className += " sepiaFW-cards-list-mixed"; //add class for mixed card body
296328
}
297329
cardElement.appendChild(cardBody);
298330

@@ -330,13 +362,26 @@ function sepiaFW_build_ui_cards(){
330362
return listInfo;
331363
}
332364
//build checkable card element (default list element)
333-
function makeUserDataListElement(elementData){
365+
function makeUserDataListElement(elementData, cardElementInfo){
366+
//console.log(cardElementInfo); //DEBUG
334367
var listEle = document.createElement('DIV');
335368
listEle.className = 'listElement cardBodyItem';
336-
if (elementData.checked){
337-
listEle.innerHTML = "<div class='listLeft checked' oncontextmenu='return false;'></div>";
338-
}else{
339-
listEle.innerHTML = "<div class='listLeft unchecked' oncontextmenu='return false;'></div>";
369+
if (cardElementInfo.indexType === INDEX_TYPE_TODO){
370+
//TODO LIST
371+
if (elementData.checked){
372+
listEle.innerHTML = "<div class='listLeft checked' oncontextmenu='return false;'></div>";
373+
}else if (elementData.state && elementData.state == "inProgress"){
374+
listEle.innerHTML = "<div class='listLeft inProgress' oncontextmenu='return false;'></div>";
375+
}else{
376+
listEle.innerHTML = "<div class='listLeft unchecked' oncontextmenu='return false;'></div>";
377+
}
378+
}else if (cardElementInfo.indexType === INDEX_TYPE_SHOPPING){
379+
//SHOPPING LIST
380+
if (elementData.checked){
381+
listEle.innerHTML = "<div class='listLeft checked' oncontextmenu='return false;'></div>";
382+
}else{
383+
listEle.innerHTML = "<div class='listLeft unchecked' oncontextmenu='return false;'></div>";
384+
}
340385
}
341386
listEle.innerHTML += "<div class='listCenter' contentEditable='true'>" + elementData.name + "</div>"
342387
listEle.innerHTML += "<div class='listRight'><i class='material-icons md-24'>&#xE15B;</i></div>";
@@ -354,43 +399,68 @@ function sepiaFW_build_ui_cards(){
354399
//left
355400
$listEle.find('.listLeft').each(function(){
356401
var that = this;
402+
var $that = $(this);
357403

358404
function shortPress(){
359405
//console.log('short-press');
360-
var isChecked;
361-
if ($(that).hasClass('checked')){
362-
$(that).removeClass('checked').addClass('unchecked');
363-
isChecked = false;
406+
//get list index-type (we do this here because it can change via drag-drop)
407+
var listContainer = $listEle.closest('.sepiaFW-cards-flexSize-container').get(0);
408+
var listInfoObj = getUserDataList(listContainer);
409+
var eleData = JSON.parse($listEle.attr('data-element'));
410+
var classesToClean = "checked unchecked inProgress";
411+
if (listInfoObj.indexType === INDEX_TYPE_TODO){
412+
//TODO
413+
if ($that.hasClass('checked')){
414+
$that.removeClass(classesToClean).addClass('unchecked');
415+
eleData.state = "open";
416+
eleData.checked = false;
417+
}else if ($that.hasClass('inProgress')){
418+
$that.removeClass(classesToClean).addClass('checked');
419+
eleData.state = "checked";
420+
eleData.checked = true;
421+
}else{
422+
$that.removeClass(classesToClean).addClass('inProgress');
423+
eleData.state = "inProgress";
424+
eleData.checked = false;
425+
}
364426
}else{
365-
$(that).removeClass('unchecked').addClass('checked');
366-
isChecked = true;
427+
//Rest of checkable types (e.g. shopping)
428+
if ($that.hasClass('checked')){
429+
$that.removeClass(classesToClean).addClass('unchecked');
430+
eleData.checked = false;
431+
}else{
432+
$that.removeClass(classesToClean).addClass('checked');
433+
eleData.checked = true;
434+
}
435+
//These type do not need a state attribue so we can remove it
436+
if (eleData.state) delete eleData.state;
367437
}
368438
//update data
369-
var eleData = JSON.parse($listEle.attr('data-element'));
370-
eleData.checked = isChecked;
371439
eleData.lastChange = new Date().getTime();
372440
$listEle.attr('data-element', JSON.stringify(eleData));
373441
//activate save button
374-
var $saveBtn = $listBody.parent().find('.sepiaFW-cards-list-saveBtn'); //note: we need to (re)load the button here
442+
var $saveBtn = $(listContainer).find('.sepiaFW-cards-list-saveBtn'); //note: we need to (re)load the button here
375443
$saveBtn.addClass('active'); //saveBtn.css({"opacity": 0.92, "color": saveBtn.parent().css("color")});
376444
}
377445

446+
function dropCallback(draggedEle, startListBody, dropListBody, positionChanged){
447+
var sameTargetContainer = startListBody.isSameNode(dropListBody);
448+
if (positionChanged){
449+
var $saveBtn = $listBody.parent().find('.sepiaFW-cards-list-saveBtn');
450+
$saveBtn.addClass('active');
451+
if (!sameTargetContainer && dropListBody){
452+
var $saveBtnNewTarget = $(dropListBody).parent().find('.sepiaFW-cards-list-saveBtn');
453+
$saveBtnNewTarget.addClass('active');
454+
}
455+
}
456+
//TODO: handle data change? (userId, listType etc.)
457+
}
458+
378459
//tap and drag handler (for sorting)
379460
//SepiaFW.ui.onclick(that, shortPress);
380461
var dragOptions = Object.assign({
381-
tapCallback: shortPress,
382-
dropCallback: function(draggedEle, startListBody, dropListBody, positionChanged){
383-
var sameTargetContainer = startListBody.isSameNode(dropListBody);
384-
if (positionChanged){
385-
var $saveBtn = $listBody.parent().find('.sepiaFW-cards-list-saveBtn');
386-
$saveBtn.addClass('active');
387-
if (!sameTargetContainer && dropListBody){
388-
var $saveBtnNewTarget = $(dropListBody).parent().find('.sepiaFW-cards-list-saveBtn');
389-
$saveBtnNewTarget.addClass('active');
390-
}
391-
}
392-
//TODO: handle data change? (userId, listType etc.)
393-
}
462+
"tapCallback": shortPress,
463+
"dropCallback": dropCallback
394464
}, udListCheckablesDragOptions);
395465
var draggable = new SepiaFW.ui.dragDrop.Draggable(that, ".listElement", ".sepiaFW-cards-list-checkables", dragOptions);
396466
});
@@ -878,7 +948,7 @@ function sepiaFW_build_ui_cards(){
878948
}
879949

880950
//----------------------------- common elements ---------------------------------
881-
951+
882952
//Card header
883953
function makeHeader(headerConfig, cardElement){
884954
var titleName = headerConfig.name;
@@ -928,6 +998,7 @@ function sepiaFW_build_ui_cards(){
928998
if(keycode == '13'){
929999
$('#sepiaFW-chat-input').focus().blur(); //workaround since SPAN can't be blurred
9301000
}
1001+
event.preventDefault;
9311002
});
9321003
}
9331004
//-context menu
@@ -955,12 +1026,10 @@ function sepiaFW_build_ui_cards(){
9551026
addItemBtn.className = "sepiaFW-cards-list-addBtn";
9561027
addItemBtn.innerHTML = '<i class="material-icons md-24">add_circle_outline</i>'; //SepiaFW.local.g('addItem');
9571028
SepiaFW.ui.onclick(addItemBtn, function(){
958-
var fakeData = {
959-
'name' : '',
960-
'checked' : false,
961-
'dateAdded' : (new Date().getTime())
962-
};
963-
var emptyEle = makeUserDataListElement(fakeData);
1029+
var listContainer = $(addItemBtn).closest('.sepiaFW-cards-flexSize-container').get(0);
1030+
var listInfoObj = getUserDataList(listContainer);
1031+
var emptyItemData = makeProductivityListObject('', listInfoObj.indexType);
1032+
var emptyEle = makeUserDataListElement(emptyItemData, listInfoObj);
9641033
var cardBody = $(addItemBtn).closest('.sepiaFW-cards-flexSize-container').find('.sepiaFW-cards-list-body');
9651034
if (cardBody.length == 0){
9661035
cardBody = document.createElement('DIV');
@@ -1030,7 +1099,8 @@ function sepiaFW_build_ui_cards(){
10301099
});
10311100
}
10321101
SepiaFW.ui.onclick(saveBtn, function(){
1033-
var listInfoObj = getUserDataList(saveBtn.parentElement.parentElement);
1102+
var listContainer = $(saveBtn).closest('.sepiaFW-cards-flexSize-container').get(0);
1103+
var listInfoObj = getUserDataList(listContainer);
10341104
//check user
10351105
if (SepiaFW.account && (SepiaFW.account.getUserId() !== listInfoObj.user)){
10361106
//different user

www/scripts/sepiaFW.ui.events.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ function sepiaFW_build_events(){
378378
}
379379
var listToLoad = {};
380380
listToLoad.section = "timeEvents";
381-
listToLoad.indexType = "alarms";
381+
listToLoad.indexType = "alarms"; //see UI.cards: INDEX_TYPE_ALARMS
382382
if (title) listToLoad.title = title;
383383
SepiaFW.account.loadList(listToLoad, function(data){
384384
//got list(s)

0 commit comments

Comments
 (0)