| 1 |
<?php |
| 2 |
/** |
| 3 |
* Section template. |
| 4 |
* |
| 5 |
* @since 3.0.0 |
| 6 |
*/ |
| 7 |
|
| 8 |
learn_press_admin_view( 'course/section-item' ); |
| 9 |
learn_press_admin_view( 'course/new-section-item' ); |
| 10 |
?> |
| 11 |
|
| 12 |
<script type="text/x-template" id="tmpl-lp-section"> |
| 13 |
<div class="section" :class="[isOpen ? 'open' : 'close', status, isEmpty ? 'empty-section' : '']" :data-section-order="index" :data-section-id="section.id"> |
| 14 |
<div class="section-head" @dblclick="toggle"> |
| 15 |
<span class="movable lp-sortable-handle"></span> |
| 16 |
<!--Section title--> |
| 17 |
<input v-model="section.title" type="text" title="title" class="title-input" @change="updating" @blur="completed" @keyup.enter="completed" placeholder="<?php esc_attr_e( 'Create a new section', 'learnpress' ); ?>"> |
| 18 |
<div class="section-item-counts"> |
| 19 |
<span v-for="item in countItems()">{{item.count}} {{item.name}}</span> |
| 20 |
</div> |
| 21 |
<!--Section toggle--> |
| 22 |
<div class="actions"> |
| 23 |
<span class="collapse" :class="isOpen ? 'open' : 'close'" @click.prevent="toggle"></span> |
| 24 |
</div> |
| 25 |
</div> |
| 26 |
|
| 27 |
<div class="section-collapse" ref="collapse"> |
| 28 |
<div class="section-content"> |
| 29 |
<div class="details"> |
| 30 |
<!--Section description--> |
| 31 |
<input v-model="section.description" type="text" class="description-input no-submit" title="description" @change="updating" @blur="completed" @keyup.enter="completed" ref="description" placeholder="<?php esc_attr_e( 'Section description...', 'learnpress' ); ?>"> |
| 32 |
</div> |
| 33 |
|
| 34 |
<div class="section-list-items" :class="{'no-item': !section.items.length}"> |
| 35 |
<ul> |
| 36 |
<!--Section items--> |
| 37 |
<lp-section-item v-for="(item, index) in section.items" :item="item" :key="item.id" @update="updateItem" @remove="removeItem" @delete="deleteItem" @nav="navItem" :order="index+1" :ref="index+1" :disableCurriculum="disableCurriculum"></lp-section-item> |
| 38 |
</ul> |
| 39 |
|
| 40 |
<lp-new-section-item @create="newItem" v-if="!disableCurriculum"></lp-new-section-item> |
| 41 |
</div> |
| 42 |
</div> |
| 43 |
|
| 44 |
<div class="section-actions" v-if="!disableCurriculum"> |
| 45 |
<button type="button" class="button button-secondary" @click="openModal"><?php esc_html_e( 'Select items', 'learnpress' ); ?></button> |
| 46 |
|
| 47 |
<div class="remove" :class="{confirm: confirm}"> |
| 48 |
<span class="icon" @click="removing"><?php esc_html_e( 'Delete', 'learnpress' ); ?></span> |
| 49 |
<div class="confirm" @click="remove"><?php esc_html_e( 'Are you sure?', 'learnpress' ); ?></div> |
| 50 |
</div> |
| 51 |
</div> |
| 52 |
</div> |
| 53 |
</div> |
| 54 |
</script> |
| 55 |
|
| 56 |
<script type="text/javascript"> |
| 57 |
window.$Vue = window.$Vue || Vue; |
| 58 |
|
| 59 |
jQuery( function( $ ) { |
| 60 |
( function( $store ) { |
| 61 |
$Vue.component( 'lp-section', { |
| 62 |
template: '#tmpl-lp-section', |
| 63 |
props: ['section', 'index', 'disableCurriculum'], |
| 64 |
data: function() { |
| 65 |
return { |
| 66 |
changed: false, |
| 67 |
confirm: false |
| 68 |
}; |
| 69 |
}, |
| 70 |
mounted: function() { |
| 71 |
var vm = this; |
| 72 |
|
| 73 |
this.prepareToggle(); |
| 74 |
|
| 75 |
this.$watch( 'section.open', function( open ) { |
| 76 |
vm.toggleAnimation( open ); |
| 77 |
}); |
| 78 |
|
| 79 |
$( this.$el ).find( '.section-list-items ul' ).sortable({ |
| 80 |
axis: 'y', |
| 81 |
//connectWith: '.section-list-items ul', |
| 82 |
handle: '.drag', |
| 83 |
start: function( e, ui ) { |
| 84 |
var id = parseInt( ui.item.attr( 'data-item-id' ) ); |
| 85 |
|
| 86 |
ui.item.data( 'vmItem', vm.section.items.filter( function( vmItem, i ) { |
| 87 |
return vmItem.id == id |
| 88 |
})) |
| 89 |
}, |
| 90 |
update: function( e, ui ) { |
| 91 |
var itemIds = $( this ).children().map( function() { |
| 92 |
return parseInt($(this).attr( 'data-item-id' ) ); |
| 93 |
}).get(); |
| 94 |
|
| 95 |
var vmItem = ui.item.data( 'vmItem' ); |
| 96 |
vm.updateOrderItems( itemIds, vmItem ? vmItem[0] : null ); |
| 97 |
} |
| 98 |
}); |
| 99 |
|
| 100 |
this.$nextTick( function() { |
| 101 |
var $ = jQuery; |
| 102 |
|
| 103 |
$( this.$el ).find( '.lp-title-attr-tip' ).LP( 'QuickTip',{ |
| 104 |
closeInterval: 0, |
| 105 |
arrowOffset: 'el', |
| 106 |
tipClass: 'preview-item-tip' |
| 107 |
}); |
| 108 |
|
| 109 |
$( document ).on( 'mousedown', '.section-item .drag', function( e ) { |
| 110 |
$( 'html, body' ).addClass( 'moving' ); |
| 111 |
}).on( 'mouseup', function( e ) { |
| 112 |
$( 'html, body' ).removeClass( 'moving' ); |
| 113 |
}); |
| 114 |
}); |
| 115 |
}, |
| 116 |
computed: { |
| 117 |
status: function() { |
| 118 |
return $store.getters['ss/statusUpdateSection'][this.section.id] || ''; |
| 119 |
}, |
| 120 |
isEmpty: function() { |
| 121 |
return isNaN( this.section.id ); |
| 122 |
}, |
| 123 |
isOpen: function() { |
| 124 |
return this.section.open; |
| 125 |
}, |
| 126 |
items: { |
| 127 |
get: function() { |
| 128 |
return this.section.items; |
| 129 |
}, |
| 130 |
set: function( items ) { |
| 131 |
this.section.items = items; |
| 132 |
|
| 133 |
$store.dispatch( 'ss/updateSectionItems', { |
| 134 |
section_id: this.section.id, |
| 135 |
items: items |
| 136 |
}); |
| 137 |
} |
| 138 |
}, |
| 139 |
optionDraggable: function() { |
| 140 |
return { |
| 141 |
handle: '.drag', |
| 142 |
draggable: '.section-item', |
| 143 |
group: { |
| 144 |
name: 'lp-section-items', |
| 145 |
put: true, |
| 146 |
pull: true |
| 147 |
} |
| 148 |
}; |
| 149 |
} |
| 150 |
}, |
| 151 |
methods: { |
| 152 |
updateOrderItems: function( orders, vmItem ) { |
| 153 |
var allItems = JSON.parse( JSON.stringify( this.section.items ) ), |
| 154 |
items = []; |
| 155 |
|
| 156 |
if ( vmItem ) { |
| 157 |
allItems.push( vmItem ); |
| 158 |
} |
| 159 |
|
| 160 |
for ( var i = 0, n = orders.length; i < n; i++ ) { |
| 161 |
$.each( allItems, function( j, item ) { |
| 162 |
if ( orders[i] === item.id ) { |
| 163 |
items.push( JSON.parse( JSON.stringify( item ) ) ); |
| 164 |
found = true; |
| 165 |
return false; |
| 166 |
} |
| 167 |
}); |
| 168 |
} |
| 169 |
|
| 170 |
this.section.items = items; |
| 171 |
$store.dispatch( 'ss/updateSectionItems', { |
| 172 |
section_id: this.section.id, |
| 173 |
items: items |
| 174 |
}); |
| 175 |
}, |
| 176 |
toggle: function() { |
| 177 |
$store.dispatch( 'ss/toggleSection', this.section ); |
| 178 |
}, |
| 179 |
prepareToggle: function() { |
| 180 |
var display = 'none'; |
| 181 |
if ( this.isOpen ) { |
| 182 |
display = 'block'; |
| 183 |
} |
| 184 |
|
| 185 |
this.$refs.collapse.style.display = display; |
| 186 |
}, |
| 187 |
toggleAnimation: function( open ) { |
| 188 |
if ( open ) { |
| 189 |
$( this.$refs.collapse ).slideDown(); |
| 190 |
} else { |
| 191 |
$( this.$refs.collapse ).slideUp(); |
| 192 |
} |
| 193 |
}, |
| 194 |
updating: function() { |
| 195 |
this.changed = true; |
| 196 |
}, |
| 197 |
completed: function() { |
| 198 |
if ( this.changed ) { |
| 199 |
$store.dispatch( 'ss/updateSection', this.section ); |
| 200 |
this.changed = false; |
| 201 |
} |
| 202 |
}, |
| 203 |
removing: function() { |
| 204 |
this.confirm = true; |
| 205 |
var vm = this; |
| 206 |
|
| 207 |
setTimeout( function() { |
| 208 |
vm.confirm = false; |
| 209 |
}, 3000 ); |
| 210 |
}, |
| 211 |
remove: function() { |
| 212 |
if ( this.confirm ) { |
| 213 |
$store.dispatch( 'ss/removeSection', { index: this.index, section: this.section } ); |
| 214 |
this.confirm = false; |
| 215 |
} |
| 216 |
}, |
| 217 |
updateItem: function( item ) { |
| 218 |
$store.dispatch( 'ss/updateSectionItem', { section_id: this.section.id, item: item } ); |
| 219 |
}, |
| 220 |
removeItem: function( item ) { |
| 221 |
$store.dispatch( 'ss/removeSectionItem', { section_id: this.section.id, item: item } ); |
| 222 |
}, |
| 223 |
deleteItem: function( item ) { |
| 224 |
$store.dispatch( 'ss/deleteSectionItem', { section_id: this.section.id, item: item } ); |
| 225 |
}, |
| 226 |
navItem: function( payload ) { |
| 227 |
var keyCode = payload.key, |
| 228 |
order = payload.order; |
| 229 |
|
| 230 |
if ( keyCode === 38 ) { |
| 231 |
if ( order === 1 ) { |
| 232 |
this.$refs.description.focus(); |
| 233 |
} else { |
| 234 |
this.nav( order - 1 ); |
| 235 |
} |
| 236 |
} |
| 237 |
|
| 238 |
if ( keyCode === 40 || keyCode === 13 ) { |
| 239 |
if ( order === this.section.items.length ) { |
| 240 |
// code |
| 241 |
} else { |
| 242 |
this.nav( order + 1 ); |
| 243 |
} |
| 244 |
} |
| 245 |
|
| 246 |
}, |
| 247 |
nav: function( position ) { |
| 248 |
var element = 'div[data-section-order=' + this.index + '] li[data-item-order=' + position + ']'; |
| 249 |
( $( element ).find( '.title input' ) ).focus(); |
| 250 |
}, |
| 251 |
newItem: function( item ) { |
| 252 |
$store.dispatch( 'ss/newSectionItem', { section_id: this.section.id, item: item } ); |
| 253 |
}, |
| 254 |
openModal: function() { |
| 255 |
$store.dispatch( 'ci/open', parseInt( this.section.id ) ); |
| 256 |
}, |
| 257 |
countItems: function() { |
| 258 |
var count = this.section.items.length, |
| 259 |
labels = $store.getters['i18n/all'].item_labels; |
| 260 |
return [{ |
| 261 |
count: count, |
| 262 |
name: count > 1 ? labels.plural : labels.singular |
| 263 |
}]; |
| 264 |
} |
| 265 |
} |
| 266 |
}); |
| 267 |
})(LP_Curriculum_Store); |
| 268 |
}); |
| 269 |
</script> |
| 270 |
|