Changeset 3699
- Timestamp:
- 07/20/2016 04:51:48 PM (10 years ago)
- Location:
- sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-payments
- Files:
-
- 1 added
- 4 edited
-
css/wordcamp-budgets.css (modified) (1 diff)
-
includes/budget-tool.php (modified) (2 diffs)
-
includes/wordcamp-budgets.php (modified) (1 diff)
-
javascript/budget-tool.js (added)
-
views/budget-tool/main.php (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-payments/css/wordcamp-budgets.css
r2878 r3699 182 182 } 183 183 184 /* Budget Tool */ 185 .wcb-budget-tool .left { 186 width: 50%; 187 float: left; 188 } 189 190 .wcb-budget-tool .right { 191 width: 50%; 192 float: left; 193 } 194 195 .wcb-budget-container { 196 width: 100%; 197 table-layout: fixed; 198 white-space:nowrap; 199 text-align: left; 200 border-collapse: collapse; 201 background: white; 202 margin: 12px 0; 203 } 204 205 .wcb-budget-container, 206 .wcb-budget-container td, 207 .wcb-budget-container th { 208 overflow: hidden; 209 text-overflow: ellipsis; 210 border: solid 1px #ccc; 211 height: 30px; 212 line-height: 30px; 213 } 214 215 .wcb-budget-container th { 216 background: #f8f8f8; 217 } 218 219 .wcb-budget-container td, 220 .wcb-budget-container th { 221 vertical-align: top; 222 padding: 0 4px; 223 } 224 225 .wcb-budget-container tr.has-changed td { 226 background: #f7ecdc; 227 } 228 229 .wcb-budget-container tr.is-new td { 230 background: #dcf7e0; 231 } 232 233 .wcb-budget-container .wcb-entry td.editable { 234 padding: 0; 235 } 236 237 .wcb-budget-container .wcb-entry input, 238 .wcb-budget-container .wcb-entry select { 239 float: left; 240 padding: 0 4px; 241 width: 100%; 242 border: 0; 243 margin: 0; 244 background: transparent; 245 -webkit-appearance: none; 246 -moz-appearance: none; 247 appearance: none; 248 border: none; 249 box-shadow: none; 250 border-radius: 0; 251 height: 30px; 252 line-height: 30px; 253 font-size: inherit; 254 cursor: default; 255 } 256 257 .wcb-budget-container .wcb-entry td.focused { 258 background: #e8f1f7; 259 border: double 1px #999; 260 } 261 262 .wcb-budget-container tr.is-new td.focused { 263 background: #ecf7ee; 264 } 265 266 .wcb-budget-container .wcb-entry input:focus { 267 cursor: text; 268 } 269 270 .wcb-budget-container .dashicons { 271 color: inherit; 272 text-decoration: none; 273 line-height: 30px; 274 color: #aaa; 275 } 276 277 .wcb-budget-container .actions { 278 text-align: right; 279 } 280 281 .wcb-budget-container tr:hover .dashicons { 282 color: #444; 283 } 284 285 .wcb-budget-container .amount { 286 text-align: right; 287 } 288 289 .wcb-budget-container .link { 290 float: right; 291 margin: -4px 4px 4px 0; 292 text-align: right; 293 font-size: 10px; 294 color: #aaa; 295 line-height: 10px; 296 } 297 298 .wcb-budget-container .wcb-entry td.focused .link-toggle { 299 opacity: 1; 300 } 301 302 .wcb-budget-container .wcb-entry td.focused .link span { 303 opacity: 0; 304 } 305 306 .wcb-budget-container .link-toggle { 307 opacity: 0; 308 position: absolute; 309 text-decoration: none; 310 color: #444; 311 } 312 313 .wcb-budget-container .link-toggle .dashicons { 314 font-size: 16px; 315 padding-left: 2px; 316 padding-right: 2px; 317 padding-top: 1px; 318 } 319 320 .wcb-budget-container .link-toggle .link-value { 321 position: absolute; 322 background: red; 323 width: 30px; 324 opacity: 0; 325 } 326 327 .wcb-expense-placeholder, 328 .wcb-income-placeholder { 329 color: #aaa; 330 font-style: italic; 331 cursor: pointer; 332 } 333 334 .wcb-budget-summary, 335 .wcb-budget-summary td, 336 .wcb-budget-summary th { 337 border-left: none; 338 } 339 340 .wcb-negative { 341 color: red; 342 } 343 344 .wcb-budget-summary .inspire { 345 color: #aaa; 346 } -
sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-payments/includes/budget-tool.php
r3302 r3699 9 9 add_submenu_page( 'wordcamp-budget', __( 'WordCamp Budget', 'wordcamporg' ), __( 'Budget', 'wordcamporg' ), 'manage_options', 'wordcamp-budget' ); 10 10 add_action( 'wcb_render_budget_page', array( __CLASS__, 'render' ) ); 11 register_setting( 'wcb_budget_noop', 'wcb_budget_noop', array( __CLASS__, 'validate' ) ); 12 } 13 14 public static function validate( $noop ) { 15 if ( empty( $_POST['_wcb_budget_data'] ) ) 16 return; 17 18 if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'wcb_budget_noop-options' ) ) 19 return; 20 21 $budget = get_option( 'wcb_budget', array() ); 22 23 // TODO: Add prelim, approved, current logic here. 24 $data = json_decode( wp_unslash( $_POST['_wcb_budget_data'] ), true ); 25 $valid_attributes = array( 'type', 'category', 'amount', 'note', 'link', 'name', 'value' ); 26 foreach ( $data as &$item ) { 27 $_item = array(); 28 foreach ( $item as $key => $value ) { 29 if ( ! in_array( $key, $valid_attributes ) ) 30 continue; 31 32 if ( $key == 'amount' ) 33 $value = round( floatval( $value ), 2 ); 34 35 $_item[ $key ] = $value; 36 } 37 38 $item = $_item; 39 print_r( $item ); 40 } 41 42 $budget['current'] = $data; 43 $budget['updated'] = time(); 44 update_option( 'wcb_budget', $budget, 'no' ); 45 return; 11 46 } 12 47 … … 14 49 $screen = get_current_screen(); 15 50 if ( $screen->id == 'toplevel_page_wordcamp-budget' ) { 16 wp_enqueue_script( 'backbone' ); 51 wp_enqueue_script( 'wcb-budget-tool', 52 plugins_url( 'javascript/budget-tool.js', __DIR__ ), 53 array( 'backbone', 'jquery', 'underscore' ), 1 , true ); 17 54 } 18 55 } 19 56 57 private static function _get_default_budget() { 58 return array( 59 array( 'type' => 'meta', 'name' => 'attendees', 'value' => 300 ), 60 array( 'type' => 'meta', 'name' => 'days', 'value' => 2 ), 61 array( 'type' => 'meta', 'name' => 'tracks', 'value' => 4 ), 62 array( 'type' => 'meta', 'name' => 'speakers', 'value' => 25 ), 63 array( 'type' => 'meta', 'name' => 'volunteers', 'value' => 10 ), 64 array( 'type' => 'meta', 'name' => 'currency', 'value' => 'USD' ), 65 array( 'type' => 'meta', 'name' => 'ticket-price', 'value' => 20.00 ), 66 67 array( 'type' => 'income', 'category' => 'other', 'note' => 'Tickets Income', 'amount' => 0, 'link' => 'ticket-price-x-attendees' ), 68 array( 'type' => 'income', 'category' => 'other', 'note' => 'Community Sponsorships', 'amount' => 4300 ), 69 array( 'type' => 'income', 'category' => 'other', 'note' => 'Local Sponsorships', 'amount' => 7000 ), 70 array( 'type' => 'income', 'category' => 'other', 'note' => 'Microsponsors', 'amount' => 500 ), 71 72 array( 'type' => 'expense', 'category' => 'venue', 'note' => 'Venue', 'amount' => 7500 ), 73 array( 'type' => 'expense', 'category' => 'venue', 'note' => 'Wifi Costs', 'amount' => 300, 'link' => 'per-day' ), 74 array( 'type' => 'expense', 'category' => 'other', 'note' => 'Comped Tickets', 'amount' => 300 ), 75 array( 'type' => 'expense', 'category' => 'audio-visual', 'note' => 'Video recording', 'amount' => 500 ), 76 array( 'type' => 'expense', 'category' => 'audio-visual', 'note' => 'Projector rental', 'amount' => 300 ), 77 array( 'type' => 'expense', 'category' => 'audio-visual', 'note' => 'Livestream', 'amount' => 200 ), 78 array( 'type' => 'expense', 'category' => 'signage-badges', 'note' => 'Printing', 'amount' => 800 ), 79 array( 'type' => 'expense', 'category' => 'signage-badges', 'note' => 'Badges', 'amount' => 8.21, 'link' => 'per-attendee' ), 80 array( 'type' => 'expense', 'category' => 'food-beverage', 'note' => 'Snacks', 'amount' => 300 ), 81 array( 'type' => 'expense', 'category' => 'food-beverage', 'note' => 'Lunch', 'amount' => 2350 ), 82 array( 'type' => 'expense', 'category' => 'food-beverage', 'note' => 'Coffee', 'amount' => 500 ), 83 array( 'type' => 'expense', 'category' => 'swag', 'note' => 'T-shirts', 'amount' => 780 ), 84 array( 'type' => 'expense', 'category' => 'speaker-event', 'note' => 'Speakers Dinner', 'amount' => 20, 'link' => 'per-speaker' ), 85 ); 86 } 87 20 88 public static function render() { 89 $budget = get_option( 'wcb_budget' ); 90 $budget = ! empty( $budget['current'] ) ? $budget['current'] : self::_get_default_budget(); 91 92 if ( ! $inspire_urls = get_site_transient( 'wcb-inspire-urls' ) ) { 93 $urls = array( 'https://jawordpressorg.github.io/wapuu/wapuu-archive/original-wapuu.png' ); 94 $r = wp_remote_get( 'https://jawordpressorg.github.io/wapuu-api/v1/wapuu.json' ); 95 if ( ! is_wp_error( $r ) && wp_remote_retrieve_response_code( $r ) == 200 ) { 96 $body = json_decode( wp_remote_retrieve_body( $r ), true ); 97 $maybe_urls = wp_list_pluck( wp_list_pluck( $body, 'wapuu' ), 'src' ); 98 if ( count( $maybe_urls ) > 0 ) { 99 $inspire_urls = $maybe_urls; 100 } 101 } 102 103 set_site_transient( 'wcb-inspire-urls', $inspire_urls, 30 * DAY_IN_SECONDS ); 104 } 105 21 106 require( dirname( __DIR__ ) . '/views/budget-tool/main.php' ); 22 107 } -
sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-payments/includes/wordcamp-budgets.php
r3306 r3699 161 161 plugins_url( 'css/wordcamp-budgets.css', __DIR__ ), 162 162 $soft_deps, 163 4163 5 164 164 ); 165 165 } -
sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-payments/views/budget-tool/main.php
r3302 r3699 1 <?php 2 $budget = array( 3 array( 'type' => 'meta', 'name' => 'attendees', 'value' => 300 ), 4 array( 'type' => 'meta', 'name' => 'days', 'value' => 2 ), 5 array( 'type' => 'meta', 'name' => 'tracks', 'value' => 4 ), 6 array( 'type' => 'meta', 'name' => 'speakers', 'value' => 25 ), 7 array( 'type' => 'meta', 'name' => 'volunteers', 'value' => 10 ), 8 array( 'type' => 'meta', 'name' => 'currency', 'value' => 'USD' ), 9 array( 'type' => 'meta', 'name' => 'ticket-price', 'value' => 20.00 ), 1 <script> 2 window.wcb = window.wcb || {models:{}, input:[]}; 3 wcb.input = <?php echo json_encode( $budget ); ?>; 4 wcb.urls = <?php echo json_encode( $inspire_urls ); ?>; 5 </script> 10 6 11 array( 'type' => 'income', 'category' => 'other', 'note' => 'Tickets Income', 'amount' => 3500 ), 12 array( 'type' => 'income', 'category' => 'other', 'note' => 'Community Sponsorships', 'amount' => 4300 ), 13 array( 'type' => 'income', 'category' => 'other', 'note' => 'Local Sponsorships', 'amount' => 7000 ), 14 array( 'type' => 'income', 'category' => 'other', 'note' => 'Microsponsors', 'amount' => 500 ), 7 <div class="wrap wcb-budget-tool"> 8 <h2 class="nav-tab-wrapper wp-clearfix"> 9 <a href="#" class="nav-tab nav-tab-active">Preliminary Budget</a> 10 <!--<a href="#" class="nav-tab">Working Budget</a>--> 11 </h2> 15 12 16 array( 'type' => 'expense', 'category' => 'venue', 'note' => 'Venue', 'amount' => 7500 ), 17 array( 'type' => 'expense', 'category' => 'venue', 'note' => 'Wifi Costs', 'amount' => 300, 'link' => 'per-day' ), 18 array( 'type' => 'expense', 'category' => 'other', 'note' => 'Comped Tickets', 'amount' => 300 ), 19 array( 'type' => 'expense', 'category' => 'audio-visual', 'note' => 'Video recording', 'amount' => 500 ), 20 array( 'type' => 'expense', 'category' => 'audio-visual', 'note' => 'Projector rental', 'amount' => 300 ), 21 array( 'type' => 'expense', 'category' => 'audio-visual', 'note' => 'Livestream', 'amount' => 200 ), 22 array( 'type' => 'expense', 'category' => 'signage-badges', 'note' => 'Printing', 'amount' => 800 ), 23 array( 'type' => 'expense', 'category' => 'signage-badges', 'note' => 'Badges', 'amount' => 8.21, 'link' => 'per-attendee' ), 24 array( 'type' => 'expense', 'category' => 'food-beverage', 'note' => 'Snacks', 'amount' => 300 ), 25 array( 'type' => 'expense', 'category' => 'food-beverage', 'note' => 'Lunch', 'amount' => 2350 ), 26 array( 'type' => 'expense', 'category' => 'food-beverage', 'note' => 'Coffee', 'amount' => 500 ), 27 array( 'type' => 'expense', 'category' => 'swag', 'note' => 'T-shirts', 'amount' => 780 ), 28 array( 'type' => 'expense', 'category' => 'speaker-event', 'note' => 'Speakers Dinner', 'amount' => 20, 'link' => 'per-speaker' ), 29 ); 30 ?> 31 <script>var wcb_data = <?php echo json_encode( $budget ); ?>;</script> 13 <p style="max-width: 800px;">Welcome to your WordCamp budget, it's time to crunch some numbers! When you're done with the preliminary budget, hit the "Submit for Approval" button below – a WordCamp deputy will be notified and will review your work. If you're having trouble with these numbers, or if you have any questions, don't hesitate to reach out to your mentor or Central.</p> 32 14 33 <div class="wrap"> 34 <h1>WordCamp Budget</h1> 35 <table id="wcb-budget-container"> 15 <div class="left"> 16 <h2>Event Data</h2> 17 <table class="wcb-budget-container"> 18 <tbody> 19 <tr class="wcb-group-header"> 20 <th style="width: 50%;">Name</th> 21 <th style="width: 50%;">Value</th> 22 </tr> 23 <tr class="wcb-meta-placeholder" style="display: none;"> 24 <td colspan="2"></td> 25 </tr> 26 </tbody> 27 </table> 28 </div> 29 <div class="right"> 30 <h2>Summary</h2> 31 <div class="wcb-summary-placeholder"></div> 32 </div> 33 34 <div class="clear"></div> 35 36 <h2>Expenses</h2> 37 <table class="wcb-budget-container"> 36 38 <tbody> 37 39 <tr class="wcb-group-header"> 38 <th colspan="4">Event Data</th> 39 </tr> 40 <tr class="wcb-meta-placeholder" style="display: none;"> 41 <td colspan="4"></td> 42 </tr> 43 <tr class="wcb-group-header"> 44 <th style="width: 200px;">Category</th> 45 <th>Detail</th> 46 <th style="width: 200px;" class="amount">Amount</th> 47 <th style="width: 100px;"></th> 48 </tr> 49 <tr class="wcb-group-header"> 50 <th colspan="4">Expenses</th> 40 <th style="width: 25%;">Category</th> 41 <th style="width: 25%;">Detail</th> 42 <th style="width: 25%;" class="amount">Amount</th> 43 <th style="width: 25%;"></th> 51 44 </tr> 52 45 <tr class="wcb-expense-placeholder"> 53 46 <td colspan="4">New Expense Item</td> 54 47 </tr> 48 </tbody> 49 </table> 50 51 <h2>Income</h2> 52 <table class="wcb-budget-container"> 53 <tbody> 55 54 <tr class="wcb-group-header"> 56 <th colspan="4">Income</th> 55 <th style="width: 25%;">Category</th> 56 <th style="width: 25%;">Detail</th> 57 <th style="width: 25%;" class="amount">Amount</th> 58 <th style="width: 25%;"></th> 57 59 </tr> 60 58 61 <tr class="wcb-income-placeholder"> 59 62 <td colspan="4">New Income Item</td> … … 62 65 </table> 63 66 64 <p class="submit"> 65 <?php submit_button( 'Save Budget', 'primary', 'submit', false ); ?> 66 <a href="#" class="button">Cancel Changes</a> 67 </p> 67 <form class="wcb-submit-form" action="options.php" method="post"> 68 <?php settings_fields( 'wcb_budget_noop' ); ?> 69 <input type="hidden" name="_wcb_budget_data" value="<?php echo esc_attr( json_encode( $budget ) ); ?>" /> 70 71 <p class="submit"> 72 <?php submit_button( 'Save Draft', 'secondary', 'wcb-budget-save-draft', false ); ?> 73 <a href="<?php echo admin_url( 'admin.php?page=wordcamp-budget' ); ?>" class="button">Cancel Changes</a> 74 <?php submit_button( 'Submit for Approval', 'primary', 'wcb-budget-submit', false ); ?> 75 </p> 76 </form> 68 77 </div> 69 78 70 <style> 71 #wcb-budget-container { 72 width: 100%; 73 table-layout: fixed; 74 white-space:nowrap; 75 text-align: left; 76 border-collapse: collapse; 77 background: white; 78 margin: 12px 0; 79 } 80 81 #wcb-budget-container, 82 #wcb-budget-container td, 83 #wcb-budget-container th { 84 overflow: hidden; 85 text-overflow: ellipsis; 86 border: solid 1px #ccc; 87 height: 30px; 88 line-height: 30px; 89 } 90 91 #wcb-budget-container th { 92 background: #f8f8f8; 93 } 94 95 #wcb-budget-container td, 96 #wcb-budget-container th { 97 vertical-align: top; 98 padding: 0 4px; 99 } 100 101 #wcb-budget-container tr.has-changed td { 102 background: #f7ecdc; 103 } 104 105 #wcb-budget-container tr.is-new td { 106 background: #dcf7e0; 107 } 108 109 #wcb-budget-container .wcb-entry-editor td { 110 background: #d5e7f4; 111 } 112 113 #wcb-budget-container .wcb-entry-editor td.editable { 114 padding: 0; 115 } 116 117 #wcb-budget-container .wcb-entry-editor input, 118 #wcb-budget-container .wcb-entry-editor select { 119 float: left; 120 padding: 0 4px; 121 width: 100%; 122 border: 0; 123 margin: 0; 124 background: transparent; 125 -webkit-appearance: none; 126 -moz-appearance: none; 127 appearance: none; 128 border: none; 129 box-shadow: none; 130 border-radius: 0; 131 height: 30px; 132 line-height: 30px; 133 font-size: inherit; 134 } 135 136 #wcb-budget-container .wcb-entry-editor input:focus { 137 background: #e8f1f7; 138 } 139 140 #wcb-budget-container .dashicons { 141 color: inherit; 142 text-decoration: none; 143 line-height: 30px; 144 color: #aaa; 145 } 146 147 #wcb-budget-container .actions { 148 text-align: right; 149 } 150 151 #wcb-budget-container tr:hover .dashicons { 152 color: #444; 153 } 154 155 #wcb-budget-container .amount { 156 text-align: right; 157 } 158 159 #wcb-budget-container .link-value { 160 display: block; 161 clear: left; 162 color: #aaa; 163 margin-top: -12px; 164 } 165 166 #wcb-budget-container .link-toggle { 167 position: absolute; 168 text-decoration: none; 169 color: #444; 170 } 171 172 #wcb-budget-container .link-toggle .dashicons { 173 font-size: 16px; 174 padding-left: 2px; 175 padding-right: 2px; 176 padding-top: 1px; 177 } 178 179 .wcb-expense-placeholder, 180 .wcb-income-placeholder { 181 color: #aaa; 182 font-style: italic; 183 cursor: pointer; 184 } 185 </style> 186 79 <script type="text/template" id="wcb-tmpl-summary"> 80 <tbody> 81 <tr class="wcb-group-header"> 82 <th style="width: 50%;"></th> 83 <th style="width: 50%;"></th> 84 </tr> 85 <tr> 86 <td>Income</td> 87 <td class="amount">{{data.income.toFixed(2)}}</td> 88 </tr> 89 <tr> 90 <td>Expenses</td> 91 <td class="amount">{{data.expenses.toFixed(2)}}</td> 92 </tr> 93 <tr> 94 <td>Variance</td> 95 <td class="amount <# if (data.variance < 0) { #>wcb-negative<# } #>">{{data.variance.toFixed(2)}}</td> 96 </tr> 97 <tr> 98 <td>Cost Per Person Per Day</td> 99 <td class="amount">{{data.per_person.toFixed(2)}}</td> 100 </tr> 101 <tr> 102 <td></td> 103 <td></td> 104 </tr> 105 <tr> 106 <td></td> 107 <td></td> 108 </tr> 109 <tr> 110 <td></td> 111 <td class="amount"> 112 <# if (data.variance < 0) { #> 113 <a href="#" target="_blank" class="inspire">inspire me</a> 114 <# } #> 115 </td> 116 </tr> 117 </tbody> 118 </script> 187 119 <script type="text/template" id="wcb-tmpl-entry"> 188 <# if (data.type == 'meta' ) { #>189 <td>{{wcb.metaLabels[data.name]}}</td>190 <td>{{data.value}}</td>191 <td></td>192 <td class="actions">193 <a href="#" class="edit"><span class="dashicons dashicons-edit"></span></a>194 </td>195 <# } else { #>196 <td>{{wcb.categories[data.category]}}</td>197 <td>{{data.note}}</td>198 <td class="amount">199 <span>{{data.realAmount.toFixed(2)}}</span>200 <# if (data.link) { #>201 <!--<span class="link-value">{{data.amount.toFixed(2)}} per attendee</span>-->202 <# } #>203 </td>204 <td class="actions">205 <a href="#" class="edit"><span class="dashicons dashicons-edit"></span></a>206 <a href="#" class="delete"><span class="dashicons dashicons-trash"></span></a>207 </td>208 <# } #>209 </script>210 <script type="text/template" id="wcb-tmpl-entry-editor">211 120 <# if (data.type == 'meta' ) { #> 212 121 <td>{{wcb.metaLabels[data.name]}}</td> … … 214 123 <input class="value" type="text" value="{{data.value}}" /> 215 124 </td> 216 <td></td>217 <td class="actions">218 <a href="#" class="save"><span class="dashicons dashicons-yes"></span></a>219 <a href="#" class="cancel"><span class="dashicons dashicons-no-alt"></span></a>220 </td>221 125 <# } else { #> 126 127 <# if (data.type == 'expense') { #> 222 128 <td class="editable"> 223 129 <select class="category"> … … 227 133 </select> 228 134 </td> 135 <# } else { #> 136 <td> 137 Income 138 <input type="hidden" class="category" value="{{data.category}}" /> 139 </td> 140 <# } #> 141 229 142 <td class="editable"> 230 143 <input class="note" type="text" value="{{data.note}}" /> 231 144 </td> 232 145 <td class="editable"> 233 <a href="#" class="link-toggle"><span class="dashicons dashicons-admin-links"></span> {{data.link}}</a> 234 <input class="amount" type="text" value="{{data.amount.toFixed(2)}}" /> 146 <div class="link-toggle"> 147 <select class="link-value"> 148 <option value="" <#if(!data.link){#>selected<#}#>>none</option> 149 <# _.each(wcb.linkData, function(item, k) { #> 150 <option value="{{k}}" <# if (data.link==k) { #>selected<# } #>>{{{item.label}}}</option> 151 <# }); #> 152 </select> 153 <span class="dashicons dashicons-admin-links"></span> 154 </div> 155 <input class="amount" type="text" value="{{data.realAmount.toFixed(2)}}" /> 156 157 <# if (data.link) { #> 158 <div class="link"> 159 <# if (data.linkHasValue) { #> 160 <span>{{data.amount.toFixed(2)}}</span> 161 <# } #> 162 163 {{{data.linkLabel}}} 164 </div> 165 <# } #> 235 166 </td> 236 167 <td class="actions"> 237 <a href="#" class="save"><span class="dashicons dashicons-yes"></span></a> 238 <a href="#" class="cancel"><span class="dashicons dashicons-no-alt"></span></a> 168 <a href="#" class="delete"><span class="dashicons dashicons-trash"></span></a> 239 169 </td> 240 170 <# } #> 241 171 </script> 242 <script type="text/template" id="wcb-tmpl-entry-link">243 <td colspan="2"></td>244 <td class="editable">245 <select class="link-value">246 <option value="" <#if(!data.link){#>selected<#}#>>None</option>247 <option value="per-attendee" <#if(data.link=='per-attendee'){#>selected<#}#>>Per Attendee</option>248 <option value="per-speaker" <#if(data.link=='per-speaker'){#>selected<#}#>>Per Speaker</option>249 <option value="per-day" <#if(data.link=='per-day'){#>selected<#}#>>Per Day</option>250 </select>251 </td>252 <td></td>253 </script>254 255 <script>256 window.wcb = window.wcb || {models:{}};257 258 (function($){259 $(document).on('budget-tool-render.wordcamp-budgets', function() {260 var $container = $('#wcb-budget-container tbody'),261 $income = $container.find('.wcb-income-placeholder'),262 $expense = $container.find('.wcb-expense-placeholder'),263 $meta = $container.find('.wcb-meta-placeholder');264 265 var template_options = {266 evaluate: /<#([\s\S]+?)#>/g,267 interpolate: /\{\{\{([\s\S]+?)\}\}\}/g,268 escape: /\{\{([^\}]+?)\}\}(?!\})/g,269 variable: 'data'270 };271 272 var Category = Backbone.Model.extend({273 defaults: {274 label: 'Category',275 value: 'category'276 }277 });278 279 var Categories = Backbone.Collection.extend({280 model: Category281 });282 283 var Entry = Backbone.Model.extend({284 defaults: {285 type: 'expense',286 category: 'other',287 amount: 0,288 note: '',289 new: false,290 link: null,291 292 // metadata293 name: '',294 value: null295 },296 297 initialize: function() {298 this._realAmount = this.getRealAmount();299 this._attr = _.clone(this.attributes);300 },301 302 getRealAmount: function() {303 if (!this.get('link'))304 return this.get('amount');305 306 if (this.get('link') === 'per-attendee') {307 var attendees = wcb.table.collection.findWhere({type: 'meta', name: 'attendees'}).get('value');308 return this.get('amount') * attendees;309 }310 311 if (this.get('link') === 'per-speaker') {312 var speakers = wcb.table.collection.findWhere({type: 'meta', name: 'speakers'}).get('value');313 return this.get('amount') * speakers;314 }315 316 if (this.get('link') === 'per-day') {317 var days = wcb.table.collection.findWhere({type: 'meta', name: 'days'}).get('value');318 return this.get('amount') * days;319 }320 321 return 0;322 },323 324 hasChanged: function() {325 // console.log(this._attr);326 // console.log(this.attributes);327 // console.log(this._realAmount)328 var changed = _.isEqual(this._attr, this.attributes) && this._realAmount == this.getRealAmount()329 return !changed;330 },331 332 editStart: function() {333 this.trigger('edit-start.wordcamp-budgets');334 }335 });336 337 var EntryView = Backbone.View.extend({338 className: 'wcb-entry',339 tagName: 'tr',340 341 events: {342 'dblclick td': 'editStart',343 'click .edit': 'editStart',344 'click .delete': 'delete',345 },346 347 initialize: function() {348 this.model.bind('change', this.render, this);349 this.model.bind('destroy', this.remove, this);350 this.model.bind('edit-start.wordcamp-budgets', this.editStart, this);351 },352 353 render: function() {354 var data = this.model.toJSON();355 data.realAmount = this.model.getRealAmount();356 357 this.template = _.template($('#wcb-tmpl-entry').html(), null, template_options);358 this.$el.html(this.template(data));359 this.$el.toggleClass('has-changed', this.model.hasChanged() && ! this.model.get('new'));360 this.$el.toggleClass('is-new', this.model.get('new'));361 return this;362 },363 364 editStart: function() {365 if (this.editing)366 return false;367 368 this.editing = true;369 this.editor = new EntryEditorView({model: this.model});370 this.editor.on('edit-save.wordcamp-budgets', this.editSave, this);371 this.editor.on('edit-cancel.wordcamp-budgets', this.editCancel, this);372 373 this.$el.after(this.editor.render().el);374 this.$el.hide();375 return false;376 },377 378 editSave: function() {379 this.clearSelection.apply(this);380 this.model = this.editor.model;381 this.editor.remove();382 this.$el.show();383 this.editing = false;384 },385 386 editCancel: function() {387 this.clearSelection.apply(this);388 this.editor.remove();389 this.$el.show();390 this.editing = false;391 },392 393 clearSelection: function() {394 if (window.getSelection) {395 if (window.getSelection().empty) {396 window.getSelection().empty();397 } else if (window.getSelection().removeAllRanges) {398 window.getSelection().removeAllRanges();399 }400 } else if (document.selection) {401 document.selection.empty();402 }403 },404 405 delete: function() {406 this.model.destroy();407 return false;408 }409 });410 411 var EntryEditorView = Backbone.View.extend({412 className: 'wcb-entry wcb-entry-editor',413 tagName: 'tr',414 415 events: {416 'click .save': 'editSave',417 'click .cancel': 'editCancel',418 'click .link-toggle': 'linkToggle',419 'keyup': 'keyup'420 },421 422 render: function() {423 this.template = _.template($('#wcb-tmpl-entry-editor').html(), null, template_options);424 this.$el.html(this.template(this.model.toJSON()));425 return this;426 },427 428 editSave: function() {429 this.model.set('amount', parseFloat(this.$el.find('.amount').val()));430 this.model.set('note', this.$el.find('.note').val());431 this.model.set('category', this.$el.find('.category').val());432 this.model.set('value', this.$el.find('.value').val() || null);433 434 if (this.linkView)435 this.model.set('link', this.linkView.$el.find('.link-value').val() || null);436 437 this.trigger('edit-save.wordcamp-budgets', this);438 if (this.linkView)439 this.linkView.remove();440 441 return false;442 },443 444 editCancel: function() {445 this.trigger('edit-cancel.wordcamp-budgets', this);446 if (this.linkView)447 this.linkView.remove();448 449 return false;450 },451 452 keyup: function(e) {453 if (e.keyCode == 27) {454 return this.editCancel.apply(this);455 } else if (e.keyCode == 13) {456 return this.editSave.apply(this);457 }458 },459 460 linkToggle: function(e) {461 if (!this.linkView) {462 this.linkView = new EntryLinkView({model: this.model});463 this.$el.after(this.linkView.render().el);464 } else {465 this.linkView.$el.toggle();466 }467 468 return false;469 }470 });471 472 var EntryLinkView = Backbone.View.extend({473 className: 'wcb-entry wcb-entry-editor wcb-entry-link',474 tagName: 'tr',475 476 events: {477 478 },479 480 render: function() {481 this.template = _.template($('#wcb-tmpl-entry-link').html(), null, template_options);482 this.$el.html(this.template(this.model.toJSON()));483 return this;484 }485 })486 487 var Entries = Backbone.Collection.extend({488 model: Entry489 });490 491 var EntriesView = Backbone.View.extend({492 tagName: 'table',493 className: 'wcb-table',494 495 initialize: function() {496 this.collection.bind('add', this.addOne, this);497 this.collection.bind('change reset', this.refresh, this);498 },499 500 refresh: function(model) {501 if (model.get('type') == 'meta') {502 this.render.apply(this);503 }504 505 return this;506 },507 508 addOne: function(item) {509 var view = new EntryView({model: item});510 switch (view.model.get('type')) {511 case 'expense':512 var $c = $expense;513 break;514 case 'income':515 var $c = $income;516 break;517 case 'meta':518 default:519 var $c = $meta;520 }521 522 $c.before(view.render().el);523 },524 525 render: function() {526 $container.find('.wcb-entry').remove();527 this.collection.each(this.addOne, this);528 return this;529 }530 });531 532 wcb.categories = {533 'venue': 'Venue',534 'audio-visual': 'Audio Visual',535 'after-party': 'After Party',536 'camera-shipping': 'Camera Shipping',537 'food-beverage': 'Food & Beverage',538 'office-supplies': 'Office Supplies',539 'signage-badges': 'Signage & Badges',540 'speaker-event': 'Speaker Event',541 'swag': 'Swag',542 'other': 'Other'543 };544 545 wcb.metaLabels = {546 'attendees': 'Attendees',547 'days': 'Days',548 'tracks': 'Tracks',549 'speakers': 'Speakers',550 'volunteers': 'Volunteers',551 'currency': 'Currency',552 'ticket-price': 'Ticket Price'553 };554 555 var table = new EntriesView({collection: new Entries()});556 557 $income.on('click', function() {558 table.collection.add(new wcb.models.Entry({559 type: 'income',560 amount: 0,561 note: 'New Income Item',562 category: 'other',563 new: true564 })).editStart();565 return false;566 });567 568 $expense.on('click', function() {569 table.collection.add(new wcb.models.Entry({570 type: 'expense',571 amount: 0,572 note: 'New Expense Item',573 category: 'other',574 new: true575 })).editStart();576 return false;577 });578 579 wcb.models.Entry = Entry;580 wcb.table = table;581 });582 }(jQuery));583 584 jQuery(document).ready(function(){585 jQuery(document).trigger('budget-tool-render.wordcamp-budgets');586 587 _.each(wcb_data, function(i){588 wcb.table.collection.add(new wcb.models.Entry(i));589 });590 });591 </script>
Note: See TracChangeset
for help on using the changeset viewer.