Changeset 490
- Timestamp:
- 08/01/07 15:08:34 (1 year ago)
- Files:
-
- pagoda/branches/cleanslate/Pagoda/pagoda/controllers/admin.py (modified) (2 diffs)
- pagoda/branches/cleanslate/Pagoda/pagoda/models/__init__.py (modified) (1 diff)
- pagoda/branches/cleanslate/Pagoda/pagoda/templates/admin/login.html (modified) (1 diff)
- pagoda/branches/cleanslate/Pagoda/pagoda/templates/admin/schedule.html (modified) (5 diffs)
- pagoda/branches/cleanslate/Pagoda/pagoda/widgets/admin/static/css/schedule.css (modified) (5 diffs)
- pagoda/branches/cleanslate/Pagoda/pagoda/widgets/admin/static/javascript/schedule.js (modified) (1 diff)
- pagoda/branches/cleanslate/Pagoda/pagoda/widgets/admin/widgets.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
pagoda/branches/cleanslate/Pagoda/pagoda/controllers/admin.py
r479 r490 148 148 # to hit the database once. 149 149 select_revisions = approve | dismiss 150 for revision in query.select(revision_id.in_(*select_revisions)): 151 if revision.revision_id in approve: 152 revision.revision_status = workflow.APPROVED 153 elif revision.revision_id in dismiss: 154 revision.revision_status = workflow.PENDING 155 156 models.session.flush() 157 return dict(success=True) 150 151 transaction = models.session.create_transaction() 152 try: 153 revisions = query.select(revision_id.in_(*selection_revisions)) 154 for revision in revisions: 155 if revision.revision_id in approve: 156 revision.revision_status = workflow.APPROVED 157 elif revision.revision_id in dismiss: 158 revision.revision_status = workflow.DRAFT 159 transaction.commit() 160 except models.exceptions.SQLAlchemyError: 161 transaction.rollback() 162 result = dict(success=False) 163 else: 164 result = dict(success=True) 165 166 return result 158 167 159 168 @expose(format='json', allow_json=True) … … 180 189 # to hit the database once. 181 190 select_revisions = release | expire | cancel_release | cancel_expire 182 for revision in query.select(revision_id.in_(*select_revisions)): 183 if revision.revision_id in release: 184 revision.revision_release_time = models.now 185 elif revision.revision_id in cancel_release: 186 revision.revision_release_time = None 187 if revision.revision_id in expire: 188 revision.revision_expire_time = models.now 189 elif revision.revision_id in cancel_expire: 190 revision.revision_expire_time = None 191 192 models.session.flush() 193 return dict(success=True) 191 192 transaction = models.session.create_transaction() 193 try: 194 revisions = query.select(revision_id.in_(*select_revisions)) 195 for revision in revisions: 196 if revision.revision_id in release: 197 revision.revision_release_time = models.now 198 elif revision.revision_id in cancel_release: 199 revision.revision_release_time = None 200 if revision.revision_id in expire: 201 revision.revision_expire_time = models.now 202 elif revision.revision_id in cancel_expire: 203 revision.revision_expire_time = None 204 transaction.commit() 205 except models.exceptions.SQLAlchemyError: 206 transaction.rollback() 207 result = dict(success=False) 208 else: 209 result = dict(success=True) 210 211 return result 194 212 195 213 class AccountsController(Controller, identity.SecureResource): pagoda/branches/cleanslate/Pagoda/pagoda/models/__init__.py
r468 r490 1 1 from turbogears.database import metadata, session 2 from sqlalchemy import exceptions 2 3 from pagoda.models.util import * 3 4 from pagoda.models.identity import * pagoda/branches/cleanslate/Pagoda/pagoda/templates/admin/login.html
r478 r490 29 29 <input type="hidden" name="forward_url" value="${forward_url}"/> 30 30 <input type="hidden" name="previous_url" value="${previous_url}"/> 31 <input py:for="name, value in original_parameters.items()" py:if="name not in ('forward_url', 'previous_url')" 32 type="hidden" name="${name}" value="${value}"/> 31 <py:for each="name, values in original_parameters.items()" py:if="name not in ('forward_url', 'previous_url')"> 32 <input py:for="value in isinstance(values, list) and values or [values]" 33 type="hidden" name="${name}" value="${value}"/> 34 </py:for> 33 35 </form> 34 36 </div> pagoda/branches/cleanslate/Pagoda/pagoda/templates/admin/schedule.html
r479 r490 16 16 17 17 <div id="body"> 18 <form id="pending" name="pending" action="pending" method=" GET" class="schedule"18 <form id="pending" name="pending" action="pending" method="POST" class="schedule" 19 19 py:with="pending_count = len(pending_revisions)"> 20 20 <h2>Pending Changes</h2> … … 27 27 <div class="date-header" py:if="pending_revisions">submission date</div> 28 28 <p class="actions-all" py:if="pending_revisions"> 29 <button type="button" name="approve" value="all"class="action-proceed" title="Approve all content—release it on the live site immediately or on its release date.">30 Approve all ( ${pending_count})29 <button type="button" name="approve" class="action-proceed" title="Approve all content—release it on the live site immediately or on its release date."> 30 Approve all (<span class="count approved">${pending_count}</span>) 31 31 </button> 32 <button type="button" name="dismiss" value="all"class="action-cancel" title="Dismiss all content—send it back for editing. No changes will be lost.">33 Dismiss all ( ${pending_count})32 <button type="button" name="dismiss" class="action-cancel" title="Dismiss all content—send it back for editing. No changes will be lost."> 33 Dismiss all (<span class="count dismissed">${pending_count}</span>) 34 34 </button> 35 35 </p> … … 86 86 <div class="date-header" py:if="scheduled_revisions">scheduled date</div> 87 87 <p class="actions-all" py:if="scheduled_revisions"> 88 <button type="button" class="action-proceed" py:if="releasing_revisions" title="Immediately release all content scheduled to be released below.">88 <button type="button" name="release" class="action-proceed" py:if="releasing_revisions" title="Immediately release all content scheduled to be released below."> 89 89 Release all now (${releasing_count}) 90 90 </button> 91 <button type="button" class="action-proceed" py:if="expiring_revisions" title="Immediately expire all content scheduled to expire below.">91 <button type="button" name="expire" class="action-proceed" py:if="expiring_revisions" title="Immediately expire all content scheduled to expire below."> 92 92 Expire all now (${expiring_count}) 93 93 </button> 94 <button type="button" class="action-cancel" title="Cancel all releases and expirations.">94 <button type="button" name="cancel" class="action-cancel" title="Cancel all releases and expirations."> 95 95 Cancel all (${scheduled_count}) 96 96 </button> … … 114 114 </p> 115 115 <p class="details"> 116 <strong py:choose="revision.was_previously_approved()"> 117 <span py:when="True">revised</span> 118 <span py:when="False">new</span> 116 <strong py:choose="is_expiration, revision.was_previously_approved()"> 117 <span py:when="True, True">live</span> 118 <span py:when="True, False">live</span> 119 <span py:when="False, True">revised</span> 120 <span py:when="False, False">new</span> 119 121 ${revision.content_type} 120 122 </strong> by ${revision.author.user_name} … … 125 127 <p class="actions" py:choose="is_expiration"> 126 128 <span py:when="0" py:strip=""> 127 <button type="button" class="action-proceed" title="Release this content—make it available on the live site immediately.">129 <button type="button" name="release" value="${revision.revision_id}" class="action-proceed" title="Release this content—make it available on the live site immediately."> 128 130 Release now 129 131 </button> 130 <button type="button" class="action-cancel" title="Cancel this release—undo approval and send the content back for editing.">132 <button type="button" name="cancel_release" value="${revision.revision_id}" class="action-cancel" title="Cancel this release—undo approval and send the content back for editing."> 131 133 Cancel release 132 134 </button> 133 135 </span> 134 136 <span py:when="1" py:strip=""> 135 <button type="button" class="action-proceed" title="Expire this content—remove it from the live site immediately.">137 <button type="button" name="expire" value="${revision.revision_id}" class="action-proceed" title="Expire this content—remove it from the live site immediately."> 136 138 Expire now 137 139 </button> 138 <button type="button" class="action-cancel" title="Cancel this expiration—keep the content on the live site until further action.">140 <button type="button" name="cancel_expire" value="${revision.revision_id}" class="action-cancel" title="Cancel this expiration—keep the content on the live site until further action."> 139 141 Cancel expiration 140 142 </button> pagoda/branches/cleanslate/Pagoda/pagoda/widgets/admin/static/css/schedule.css
r479 r490 11 11 } 12 12 13 .schedule { 14 width: 50em; 15 margin: 0 auto; 16 padding: 2em; 17 background: #fff; 18 border: 1px solid #bbb; 19 text-align: left; 20 } 21 13 22 .schedule .date-header, 14 23 .schedule .date-group { … … 18 27 width: 11em; 19 28 margin-left: -14em; 29 padding-right: 3em; 20 30 } 21 31 22 32 .schedule .date-header { 23 padding-top: 2 em;33 padding-top: 2.5em; 24 34 color: #888a85; 25 35 } … … 29 39 margin-top: 0.5em; 30 40 color: #555753; 31 }32 33 .schedule {34 width: 50em;35 margin: 0 auto;36 padding: 2em;37 background: #fff;38 border: 1px solid #bbb;39 text-align: left;40 41 } 41 42 … … 70 71 .schedule ul li.empty { 71 72 text-align: center; 73 } 74 75 .schedule ul li.approved, 76 .schedule ul li.dismissed { 77 } 78 79 .schedule ul li.approved .status, 80 .schedule ul li.dismissed .status { 81 margin-bottom: 0; 82 font-weight: bold; 83 } 84 85 .schedule ul li.approved .title, 86 .schedule ul li.dismissed .title { 87 font-size: 100%; 88 } 89 90 .schedule ul li.approved .details, 91 .schedule ul li.dismissed .details { 92 display: none; 93 } 94 95 .schedule ul li.approved .actions, 96 .schedule ul li.dismissed .actions { 97 display: none; 72 98 } 73 99 … … 109 135 } 110 136 137 .schedule button:disabled, 138 .schedule button:disabled:hover, 139 .schedule button:disabled:focus, 140 .schedule button.disabled, 141 .schedule button.disabled:hover, 142 .schedule button.disabled:focus { 143 color: #bbb !important; 144 border-color: #ccc; 145 } 146 111 147 .schedule button:hover, 112 148 .schedule button:focus, pagoda/branches/cleanslate/Pagoda/pagoda/widgets/admin/static/javascript/schedule.js
r458 r490 1 // Ext.ObservableElement = function() { 2 // // constructor 3 // Ext.ObservableElement.superclass.constructor.call(this, arguments); 4 // this.events = {}; 5 // } 6 // 7 // Ext.extend(Ext.ObservableElement, Ext.Element, {}); 8 // Ext.applyIf(Ext.ObservableElement.prototype, Ext.util.Observable.prototype); 1 var clickSubmits = function(submitForm, clickSelector, itemSelector) { 2 submitForm.el.select(itemSelector).each(function() { 3 var item = this.dom || this; 4 this.select(clickSelector).each(function() { 5 var el = this.dom || this; 6 Ext.EventManager.addListener(this, 'click', function() { 7 var buttonParams = {}; 8 var items = {}; 9 items[el.name] = [item]; 10 buttonParams[el.name] = [el.value]; 11 submitForm.doAction('submitparams', {params: buttonParams, items: items}); 12 }); 13 }); 14 15 }); 16 } 17 18 var clickSubmitsAll = function(submitForm, clickSelector, valueSelector, itemSelector, itemFilters) { 19 var itemFilters = itemFilters || []; 20 submitForm.el.select(clickSelector).each(function() { 21 var el = this.dom || this; 22 Ext.EventManager.addListener(this, 'click', function() { 23 var allParams = {}; 24 var items = {}; 25 var selection = submitForm.el.select(itemSelector); 26 for (var i = 0; i < itemFilters.length; i++) { 27 selection = selection.filter(itemFilters[i]); 28 } 29 selection.each(function() { 30 var item = this.dom || this; 31 this.select(valueSelector).each(function() { 32 var buttonEl = this.dom || this; 33 if (allParams[buttonEl.name]) { 34 allParams[buttonEl.name].push(buttonEl.value); 35 } 36 else { 37 allParams[buttonEl.name] = [buttonEl.value]; 38 } 39 if (items[buttonEl.name]) { 40 items[buttonEl.name].push(item); 41 } 42 else { 43 items[buttonEl.name] = [item]; 44 } 45 }); 46 }); 47 submitForm.doAction('submitparams', {params: allParams, items: items}); 48 }); 49 }); 50 } 51 52 var setupListSubmit = function(info) { 53 info.form.on('actioncomplete', info.success, info.form); 54 info.form.on('actionfailed', info.failure, info.form); 55 56 for (var name in info.one) { 57 clickSubmits(info.form, info.one[name], info.selector); 58 } 59 for (var name in info.all) { 60 clickSubmitsAll(info.form, info.all[name], info.one[name], info.selector, info.filters); 61 } 62 } 9 63 10 64 Ext.onReady(function() { 11 var pendingForm = new Ext.form.BasicForm('pending'); 12 13 // var pendingForm = new Ext.ObservableElement('pending'); 14 15 pendingForm.on('submit', 16 function(button) { 17 var approveRevision = button.getValue(); 18 if (approveRevision == 'all') { 19 console.log("Approving revisions..."); 65 var pendingForm = new Ext.BasicForm('pending'); 66 pendingForm.pagodaSetup = { 67 form: pendingForm, 68 selector: "ul li", 69 filters: [":not(.approved)", ":not(.dismissed)"], 70 one: {approve: ".actions button[name=approve]", dismiss: ".actions button[name=dismiss]"}, 71 all: {approve: ".actions-all button[name=approve]", dismiss: ".actions-all button[name=dismiss]"}, 72 status: {approve: "approved", dismiss: "dismissed"}, 73 cls: {approve: 'approved', dismiss: 'dismissed'}, 74 success: function(form, action) { 75 var processedCount = 0; 76 for (var name in action.options.items) { 77 var items = action.options.items[name] || []; 78 for (var i = 0; i < items.length; i++) { 79 var el = Ext.get(items[i]); 80 el.sequenceFx(); 81 el.fadeOut({ 82 duration: 0.25, 83 afterCls: form.pagodaSetup.cls[name], 84 scope: el, 85 callback: function() { 86 this.select('.status').update(form.pagodaSetup.status[name]); 87 } 88 }); 89 el.fadeIn({ 90 duration: 0.25, 91 endOpacity: 0.5 92 }); 93 } 94 processedCount += items.length; 20 95 } 21 else { 22 console.log("Approving revision ", approveRevision, "..."); 96 97 var approveCount = form.el.select('.count.approved'); 98 var dismissCount = form.el.select('.count.dismissed'); 99 var stillPendingCount = approveCount.first().dom.innerHTML - processedCount; 100 approveCount.update(stillPendingCount); 101 dismissCount.update(stillPendingCount); 102 103 if (!stillPendingCount) { 104 Ext.select(form.pagodaSetup.all.approve).set({disabled: true}); 105 Ext.select(form.pagodaSetup.all.dismiss).set({disabled: true}); 23 106 } 24 107 }, 25 pendingForm 26 ); 27 // var dismissAll = Ext.select('#pending .actions-all button.action-cancel'); 28 var approveButtons = Ext.select('#pending button.action-proceed'); 29 // var dismissButtons = Ext.select('#pending .actions button.action-cancel'); 30 approveButtons.on('click', 31 function(e) { 32 var button = Ext.get(this); 33 pendingForm.fireEvent('submit', button); 108 failure: function(form, action) { 109 console.log('ERROR!'); 110 console.log('form: ', form); 111 console.log('action: ', action); 34 112 } 35 ); 113 }; 114 setupListSubmit(pendingForm.pagodaSetup); 115 116 var scheduledForm = new Ext.BasicForm('scheduled'); 117 scheduledForm.pagodaSetup = { 118 form: scheduledForm, 119 selector: "ul li", 120 filters: [":not(.released)", ":not(.expired)"], 121 one: { 122 release: ".actions button[name=release]", 123 expire: ".actions button[name=expire]", 124 cancel: ".actions button[name^=cancel]" 125 }, 126 all: { 127 release: ".actions-all button[name=release]", 128 expire: ".actions-all button[name=expire]", 129 cancel: ".actions-all button[name=cancel]" 130 }, 131 status: {release: "released", expire: "expired", cancel: "cancelled"}, 132 cls: {release: 'released', expire: 'expired', cancel: 'canceled'}, 133 success: function(form, action) { 134 console.log('SUCCESS!'); 135 console.log('form: ', form); 136 console.log('action: ', action); 137 }, 138 failure: function(form, action) { 139 console.log('ERROR!'); 140 console.log('form: ', form); 141 console.log('action: ', action); 142 } 143 }; 144 setupListSubmit(scheduledForm.pagodaSetup); 36 145 }); pagoda/branches/cleanslate/Pagoda/pagoda/widgets/admin/widgets.py
r482 r490 59 59 schedule_base = JSLink( 60 60 modname=module_name, filename='static/javascript/schedule.js', 61 css=[schedule_css], javascript=[admin_base ]61 css=[schedule_css], javascript=[admin_base, submit_params] 62 62 ) 63 63
