Jump to content

Graham Quince

  • Posts

  • Joined

  • Last visited

Everything posted by Graham Quince

  1. Obviously Paul has won this. Well done @pconkie - we've got slight issue with publishing his app, so I can't share it yet - but I'll be sharing here as soon as I can.
  2. Hi @gbligh, Looks like we need to add an IF statement to check for only assignments with start dates less than the current dates. Try this: <style> .row-template { display: none; } .assignment-widget-header { background-color: #231f20; padding: 1em; position: relative; text-align: left; } .assignment-widget-header::after { content: ""; width: 98%; height: 60%; position: absolute; top: 3%; left: 1%; border-radius: 5px; } .assignment-widget-header h1 { color: #fff; font-size: 20px; margin: 0; } .no-homework { padding: 1em; text-align: center; } .assignment-list { list-style: none; padding: 0 1em; margin:0 0 0 0; } .assignment-list :hover{ background-color:#ededed; } .assignment-list .assignment-link { border-bottom: 1px solid #ddd; padding: 10px 10px 10px 10px; margin: 0.5em 0; cursor: pointer; } .assignment-list .assignment-link p { margin: 0; } .assignment-list .assignment-link .assign-icon { width: 32px; height: 32px; display: block; float: left; margin-top: 2px; background: url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCAAgACADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDtfAvgzxT8eoW8W6j4l1meW+1Gb+0JYvEE9rFp0PmSYIhSRQkKJGQPU8euNH4N/DrQPFXxs8a6Hea54t8R+GdI8PrqVkLXxBqEcs7/AGmVCy7ZgzFkQKFJwTyBzXk/w/8AAvjDXtA05NG8W6nZQ6rPLYR2dtpsTxEtcOfJMh+8CVL4bsCegr0n4D/DPx1p/wC0B4w0WD4nz+GdU0vw7E15qaaXZzKY1upB5ZDAoFUgtuGDzg9K+TwdWUsY1zN6vvbytpY8LDzlLEWu3q+//DHRLqHwyYA/8Kn/AGgf+/8Aq/8A8l1p3Z0rwp4Hi+JXgKw+JHgjVNF8Q6fYTaf4zvb1o9SguJ4opEaC4lkDJtl4YYIZa7b7Vq3/AEeFpP8A4B6NXGfHDQ/E198KW1g/HiP4kaFa67pMVzp9pp1gImc30G0NLANylSytjPOOeDX1R7p4f8L/AI1eOfAPgxtL8P8Ah3WJrK6M6C5gltiu4zSDzYA0gZHwSmcZx26EdX+zh488QaD8aPEzQfCjxB4imuPDUVnc6PHPZiVY/tUu55PNlClWJZduScg5GOaZ4D+IWj/A2zufDXjXwu6eKtFvZprNru0nG2YSyeW5KqRLbkOJFwfvD8RqfAr45eGNM+OHjLxH4p8T3FjFrXhuO0/taGynVvtJuZWYIBEdrKrKRxjp1r5XB05Rxl5Rf2v5rLXz018jwsPFrEarv30/T7j1UabonT/hiuT/AMAtC/8Aj1ct8ZPEFxpfwnfQdN/Z+1L4X6Pe69pM9zfxjTYrZZFvoMM6W8pYs21UB2nqM4FKPEnwz/6Oo+Kf/fw//INTa94h8P8AjjwHB8OPA/j3xb8WfEWteIdNu/P12GR/7Ot4LiKWV3l8iNUiCxHrklnGK+qPdP/Z) no-repeat; } .assignment-list .assignment-link .assign-details { padding: 0 1em; float: left; } .widget-header { width: 100%; height:50px; line-height:50px; vertical-align:top; padding-left: 20px; box-sizing: border-box; background-color: #0497da; border-top-left-radius: 6px; border-top-right-radius: 6px; border: 1px solid #cccccc; border-bottom-width: 0; color: #ffffff; font-size:12pt; background: #0497da; /* Old browsers */ background: -moz-linear-gradient(top, #0497da 0%, #0064cd 100%); /* FF3.6-15 */ background: -webkit-linear-gradient(top, #0497da 0%,#0064cd 100%); /* Chrome10-25,Safari5.1-6 */ background: linear-gradient(to bottom, #0497da 0%,#0064cd 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0497da', endColorstr='#0064cd',GradientType=0 ); /* IE6-9 */ } .widget-body { background-color: white; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border: 1px solid #cccccc; border-top-width: 0; } </style> <div class="widget-header"> This week's homework: </div> <div class="widget-body"> <p class="no-homework">You've not been set any homework yet</p> <ul class="assignment-list" style="display: none;"> </ul> </div> <script> var getHTMLElem = arguments[0]; var assignments = FrogOS.fdp({ url: 'assignment/getAssigned', data: { status: 'open', limit: 15, order: 'start desc' } }); assignments.done(function(data) { var assignments = data.response.assignments, assignment; for (var uuid in assignments) { if (assignments.hasOwnProperty(uuid)) { assignment = assignments[uuid].assignment; var currentDate = moment()/1000; /// Convert from miliseconds to seconds getHTMLElem.find('.assignment-list').show(); getHTMLElem.find('.no-homework').hide(); if (assignment.start < currentDate){ var assignSubject = '<p><strong>' + assignment.subject.name + '</strong></p>'; var assignTitle = '<p>' + assignment.name + '</p>'; var assignEnd = '<p style="color: red;"><strong>Due: ' + moment(assignment.end, 'X').format('Do MMM YYYY') + '</strong></p>'; var assignLink = assignment.link; var liElem = '<li class="assignment-link clearfix" data-assignment-link="' + assignLink + '"><div class="assign-icon"></div><div class="assign-details">' + assignSubject + '' + assignTitle + '' + assignEnd + '</div></li>'; getHTMLElem.find('.assignment-list').append(liElem); } } } }); $(getHTMLElem).on('click', '.assignment-link', function(el){ $(this).trigger('os.app.siteviewer', { data: { site: el.currentTarget.dataset.assignmentLink } }); }); </script>
  3. Didn't intend for this to be so soon, but I've had to update the Page Menu / Headlines widget. Version: 0.3.0 Altered the way the widget responds to page rules
  4. In order to help you know when a FrogCode widget or application is updated, I've created this thread. If you use the Follow button, you'll be emailed when there is a new post here. My plan is to make a new post whenever there is an update to any widget. And take a look at this code for an HTML widget to let you know what versions of each widget you have: For reference, here's all the version numbers of active FrogCode widgets - date: 6/9/21 Applications: Assignment Look-up - v. 0.0.4 Document Analytics - v. 0.0.7 Seating Plans - v. 3.2.8 Widgets: Activity Timer - v 0.0.2 Assignment Activity Hand-ins - v 0.0.14 Assignment Open Report - v 0.1.2 Assign with Title - v 0.0.3 Card Sort - v 0.0.2 Data to Form - v 0.0.3 Diamond Nine - v 0.0.2 Dice - v 0.0.3 Digital Signage - v 0.0.1 Directory - v 0.0.2 eBooks - v 0.0.3 Email Alert - v 0.0.2 ePortfolio Embed - v 0.0.1 ePortfolio Groups - v 0.0.6 ePortfolio User Details - v 0.0.8 Event Countdown - v 0.0.3 Exam Timetables - v 0.0.4 External Links on your Site's Navigation - v 0.0.2 Flash Cards - v 0.1.1 Folders (Site Assets) - v 0.0.2 Folder Search - v 0.0.1 Fund-Raising Thermometer - v 0.1.1 Google Folder Embed - v 0.0.3 Google Search - v 1.1.2 Groups Contextual Data - v 0.0.1 House Points Bar Chart - v 0.0.2 Image Slider - v 0.1.3 Join a Group - v 0.0.5 Learning Locker - v 0.1.2 Link Log - v 0.0.3 Link to File Lozenge - v 0.0.4 Link to Page Lozenge - v 0.0.5 MS Stream - v 0.0.1 Multi-File Upload (FrogDrive Folder) - v 0.2.4 My Notifications - v 0.2.02 365 Document Viewer - v 0.0.4 OpenDyslexic - v 0.1.1 Opinion Line - v 0.2.5 Padlet - v 0.0.3 Page Menu - v 0.2.6 Paper Cut - v 0.0.3 Personalised Welcome - v 0.0.2 Picture Series - v 0.0.7 QR Code - v 0.0.8 Set Keyword and Email - v 0.06 Set My Preferences - v 0.0.1 Site Favourites - v 0.0.2 Site Search - v 0.0.3 Site Sharing Status - v 0.0.3 Staff Parent Child Selector - v 0.0.2 Staff Remote Access - v 0.0.1 Style Control - v 0.0.4 Task Randomiser - v 0.0.1 Telephone Link - v 0.0.2 Traffic Light - v 0.0.1 Twitter Feed - v 0.0.4 Visitor Log - v 0.2.3 Week Indicator - 0.0.2 Who am I teaching? - v 0.0.2
  5. Here's a snippet I've just put together which you can drop into an HTML widget and get a list of all your installed FrogCode applications and widgets with their version number. Might make keeping track of what you're got easier: <style> .packageList { font-size: 11pt !important; width: calc(50% - 45px); float: left; margin: 5px; background: #FFFFFF; border: 1px solid #cccccc; padding: 10px; border-radius: 7px; } .packageIcon { width: 35px; height: 35px; margin-right: 10px; } .packageItem { width: 100%; margin-bottom: 5px; } </style> <div class="packageList"> <table class="installedApps"></table> </div> <div class="packageList"> <table class="installedWidgets"></table> </div> <script> Frog.Model.api('packages.get', { enabled: true }).done(function(response) { var apps = response.data.app; var widgets = response.data.widget; widgets.sort(sortFunction); for (var a = 0; a < apps.length; a++) { listPackage(apps[a].extended_data.appname,apps[a].extended_data.version,apps[a].extended_data.appicon,'installedApps'); } for (var w = 0; w < widgets.length; w++) { listPackage(widgets[w].name,widgets[w].extended_data.version,widgets[w].extended_data.icon,'installedWidgets'); } }).fail(function(e) { console.log("FAILED"); }); function sortFunction(a, b) { if (a.name.toLowerCase() === b.name.toLowerCase()) { return 0; } else { return (a.name.toLowerCase() < b.name.toLowerCase()) ? -1 : 1; } } function listPackage(appName, version, icon, type) { $('.'+type).append( '<tr class="packageItem">'+ '<td><img class="packageIcon" src="'+icon+'"></td>'+ '<td>'+appName+' </td>'+ '<td>Version: <b>'+version+'</b>'+'</td>'+ '</tr>' ); } </script>
  6. Here's an interesting snippet should anyone need it. A school deleted a collection, but kept the ePortfolios as sites, not realising that this meant the sharing would be transferred to each site. They were faced with manually altering 1000 sites, so I helped them with this: <div class="btn btn-danger shareChange">Change Teacher Comments share</div> <div class="shareStatus"></div> <script> var SEARCH_TERM = "old sites"; function getSites() { Frog.Model.api('sites.search', { exclude_sources: ["temporary"], filter: {is_eportfolio: "0"}, include_associations: "true", limit: "1000", offset: "0", order: {updated: "desc"}, query: SEARCH_TERM, requires: {columns: "false"}, scope: "global" }).done(function(response) { var sites = response.data.sites; $('.shareStatus').text("Found: "+sites.length); onebyone(sites,0); }).fail(function(e) { console.log("FAILED"); }); } function onebyone(allSites,i) { console.log(i); if (i < allSites.length) { if (i == 100 || i == 200 || i == 300 || i == 400 || i == 500 || i == 600 || i == 700 || i == 800 || i == 900 || i == 1000) { $('.shareStatus').html('Pausing for 1 minute to prevent maxing out API requests'); setTimeout(function(){ changeshare(allSites,i); }, 60000); } else { $('.shareStatus').html('Running '+i+' of '+ allSites.length); changeshare(allSites,i); } } } function changeshare(allSites,i) { Frog.Model.api('sites.sharing.set', { associations: {template: "0"}, external_url: allSites[i].external_url, is_external: "false", site: allSites[i].uuid },{ type: 'POST' }).done(function(response) { }).fail(function(e) { console.log("FAILED to share :"+i+" - "+allSites[i].uuid); }); Frog.Model.api('share.set', { permissions: 'none', target: allSites[i].uuid },{ type: 'POST' }).done(function(response) { }).fail(function(e) { console.log("FAILED to share :"+i+" - "+allSites[i].uuid); }); i = i+1; onebyone(allSites,i); } $('.shareChange').click(function(){ getSites(); }); </script> This removed the individual shares, although I had to go back over it and remove the profile shares. To do that, I removed the shares from one site and observed the API call. The permissions for share.set were stored as an object. The search term is what was a searched for in FrogDrive > Sites to identify the sites to change.
  7. Hi everyone, Over the last year we've had a couple of minor requests for changes to Seating Plans, which led to a version mismatch. (If you have a Delete All button, then you cannot make seating plans for registration groups, if you can make reg groups, then you won't have the delete all button) Changes for version 3.2.8, released: 2nd September 2021: Underneath the existing Delete button (which removes plans created in the previous year), there is a Delete All button which removes all Seating Plans. These buttons are only visible to the admin profile. You can now create Seating Plans for any group in Frog, not just classes. Previous versions of Seating Plans only retrieved plans created within 20 days of the current academic year. Admittedly we didn't check with Paul about that reasoning, but it was causing confusion so now Seating Plans returns all plans created. You'll need to use the Delete buttons to remove older plans. The developers at Frog are responsible for these changes, given our commitment to support Seating Plans for schools. I've forever grateful to our Frog Community Genius @pconkie for sharing. You can download the latest version of Seating Plans from this link: https://schools.frogeducation.com/community/frogcode/frogcode-showcase/seatingplans
  8. We've got a school keen to reuse their class sites, but they've made extensive use the Site Timeline for galleries. (Biggest one had 7.5Gb of files in the timeline) There's various support / dev options possible, but seeing as all they wanted was the exact same site without any pictures attached, I've prepared this code for an HTML widget. It's not 100% perfect (i.e. it could do with tidying up) but it clears out a site's timeline in the background: Site UUID: <input type="text" id="uuid" class="siteuuid" name="siteuuid"><br> <div class="btn btn-warning assetDELETE">DELETE Loads of Timeline Assets</div> <div class="deleteStatus"></div> <script> function deleteOldAssets() { var siteUUID = $('.siteuuid').val(); if (siteUUID) { console.log(siteUUID); Frog.Model.api('timeline.search', { context: siteUUID, limit: "2500", refresh: "true", requiredKeywords: ["timeline asset"], since: "0", target: "62D1A1EE20025294051F3FC408A84B01A904A4FC50D3E7CE" }).done(function(response) { var events = response.data.events; $('.deleteStatus').text("Found: "+events.length+" images"); for (var i = 0; i< events.length; i++) { Frog.Model.api('timeline.deleteevent', { uuid: events[i].uuid },{ type: 'POST' }).done(function(response) { console.log("DELETED"); }).fail(function(e) { console.log("FAILED"); }); } }).fail(function(e) { console.log("FAILED"); }); } } To get the Site UUID, I used Chris Smith's bookmarklet:
  9. Here's Chris Smith bookmarklet to easily grab a site's UUID From Wikipedia: Whenever I need to get a site's uuid, I have to right-click on the site, choose "inspect" or "inspect element" then scroll through the developer tools to spot the uuid. javascript:$(".os_core:first").one("click", function(ev) { var i = jQuery(ev.originalEvent.target), p = document.createElement('p'), l, r, s; i.is(".sites_core") || (i = i.closest(".sites_core")); l = i.data('controllers').sites_core.site.uuid; p.innerText = l; document.body.appendChild(p); if (document.body.createTextRange) { r = document.body.createTextRange(); r.moveToElementText(p); r.select(); } else if (window.getSelection) { s = window.getSelection(); r = document.createRange(); r.selectNodeContents(p); s.removeAllRanges(); s.addRange(r); } if (document.execCommand('copy')) { Frog.Controller.prototype.growl('Site UUID copied to clipboard', 'FrogOS Developer Tools', 'configmanager'); } else { window.prompt("Copy to Clipboard: Ctrl+C, Enter", l); } if ('remove' in Element.prototype) { p.remove(); } else { document.body.removeChild(p); } }); To make: Make a bookmark to a random page Edit the bookmark Replace the link with the code above To use: Click on the bookmarklet Click on the site- the Site's UUID will be copied to your clipboard.
  10. We have a complete guide to end-of-year / start-of-year housekeeping on this link: https://schools.frogeducation.com/community/training/housekeeping This link shows the steps involved in arching old users: https://schools.frogeducation.com/community/training/housekeeping/froglearn/old-users And this one shows how to get rid of old groups: https://schools.frogeducation.com/community/training/housekeeping/froglearn/groups
  11. Rather than try to fix Simon's widget, I've retired it and added in these features to the Page Headlines/Menu widget. It should do the same job.
  12. You can create accounts for new staff in the regular way using the Users app and the new user button. When the new academic year starts, there is an option in the Action Cog to reassign the MIS link to the account you created earlier. Once the new academic year starts, find the newly created account for the staff member, the new one will have a tick in the MIS column: And in the Action Cog, look for Reassign MIS Link. This pop-up will open: Frog will do its best to identify the appropriate account to switch to, but you can also search for the user in the Assign to search box. Once completed, you can archive the now un-needed account. Automatic importing is also possible (with a few steps) if SIMS The SIMS extractor does include an option for pre-admissions for staff, students and parents. However, Frog creates these accounts as Inactive. To use effectively, you need to follow these steps: Check the box for pre-admission in the extractor Once an import has run, uncheck the box - if the checkbox remains checked, the accounts will become Inactive at next import. Export all users (or just parents....) via the Users app and amend the CSV to make the accounts Active. Import this CSV
  13. Before you return in September. It's currently undergoing last of the testing - and we really wanted it ready before the break, but it's looking too tight to make that end of term deadline.
  14. While the widget will display the information for you, you can use this code to retrieve it for yourself: <div class="my_data"></div> <script> var myDataDiv = arguments[0].find('.my_data'); var user = FrogOS ? FrogOS.getUser() : self.getUser(); var formUUID = 'FORM_UUID'; Frog.Model.api('dataviewer.gettable', { content_uuid: formUUID, current_user_only: 'false', form_uuid: formUUID, limit: 1, module: 'form', offset: '0', sort_dir: 'DESC', sort_field: 'date' }).done(function(response) { var personalData = response.data; $.each(personalData, function(index, entry) { var data = entry.fields[1].responses[0].response; data = JSON.parse(data); $.each(data, function(index, datum) { if (datum) { myDataDiv.append( index+ ' : '+ datum ) } }) // end of data $.each }); // end of personalData $.each }); // end of API response </script>
  15. I've been working on this widget for some time and I think it solves a big issue for everyone. If your experience working in school was anything like mine, at some point, you will have wanted to display personal data back to the logged in user that did not originate from the MIS. Things like: Login credentials for 3rd Party systems Account balances for cashless catering Appointment times Times of music lessons Short term grades Personal revision links Tutor details Reward points After School clubs Exam timetables (?) I've come up with widget which allows you to add a spreadsheet into a Form. You do have to set the form up first (although the widget contains instructions on what you need to do). Once the information is in, you can use Access Control to set privacy settings. You can download the widget from this link: https://schools.frogeducation.com/community/frogcode/frogcode-showcase/data2form For those of you looking for a way to replicate Frog3 custom fields, this widget should help you achieve that.
  16. Graham Quince


    I think there's a few more too, but to be honest, I'd be reluctant to publish a list as it probably wouldn't get updated when different teams add SSO. Here's a list I've been able to find. There are two styles of integrations AppWrapper (old integration - limited support) / SAML (current way that Frog integrates with all 3rd parties) AppWrapper Integrations ClickView (integration via Discover) Encyclopedia Britannica (Advanced, Intermediate, Foundation, Image Quest) Espresso GCSEPod Planet eStream PurpleMash SAML Integrations ClickView MintClass Room Booking System The Day Times Tables Rock Stars U-Explore And of course, any system which uses ADFS. iSAMS is currently being developed
  17. Graham Quince


    I'm not aware of Provision Map. There's been discussions about CPOMS but currently we don't have anything for that.
  18. Just to update on this, the API has been updated and UUIDs will be included in the response in that update.
  19. I thought I'd share this snippet more for reference than for a specific need, but it saves you have to work it out later. It uses an FDP API (fixed so they will not be changed, unlike the internal APIs) This is example, it was needed to change the site's background and banner to match a student's house colours. I know I could have set the CSS in Javascript, but pages load on demand and by rendering out the CSS, it is easy to adapt for all sites, or all pages etc... <div class="styling"></div> <script> var siteUUID = 'SITE_UUID', user = FrogOS ? FrogOS.getUser() : this.getUser(), styling = arguments[0].find('.styling'); houseColours = { 'House1': { background: 'rgba(0,255,0,1)', banner: 'file/resource/7E4864D720030D3DB0338F5280C6A104F3BB61EC80ADD2A4' }, 'House2': { background: 'rgba(255,0,0,1)', banner: 'file/resource/7E4864D720030D3DB0338F5280C6A104F3BB61EC80ADD2A4' }, 'House3': { background: 'rgba(255,255,0,1)', banner: 'file/resource/7E4864D720030D3DB0338F5280C6A104F3BB61EC80ADD2A4' }, 'House4': { background: 'rgba(0,0,255,1)', banner: 'file/resource/7E4864D720030D3DB0338F5280C6A104F3BB61EC80ADD2A4' } }; if (user.profile.type == 'admin' || user.profile.type == 'superuser') { user.uuid = 'STUDENT_UUID'; } FrogOS.fdp({ url: 'group/memberships', path: '/api/fdp/2/', data: { uuid: user.uuid } }).done(function(response) { var house = 'House1'; var groups = response.response; $.each(groups, function(index,group) { if (group.type == 'house') { house = group.name; } }); var background = houseColours[house].background, banner = houseColours[house].banner; styling.html( '<style>'+ 'div[data-site-uuid="'+siteUUID+'"] .ui-theme-mobilesmallbanner-bodyline {'+ 'background: '+background+' !important;'+ 'background: linear-gradient(180deg, '+background+' 0%, rgba(255,255,255,1) 20%) !important;'+ '}'+ 'div[data-site-uuid="'+siteUUID+'"] .ui-theme-mobilesmallbanner-container {'+ 'background-image: url('+banner+') !important;'+ '}'+ '</style>' ) }).fail(function(e) { // Report Error console.log("failed"); }); </script>
  20. To celebrate my new tutorial for on how to build your own Random Name Selector we’re running a competition for the best widget (or application) you can build over the summer. Submit your widget by 14th September (National Coding Week) and the winning entry will receive a Frog hoodie. We’ll proudly host all widgets on the community for everyone to enjoy. How to submit: Reply to this thread with the name of your Widget and screenshots / videos of your action in action. You can either submit your own variation on the Random Name Selector or your own brand new widget. Use the Coding forum if you have any questions.
  21. Before you start, you’ll need access to the FrogCode Editor. Contact the Service Desk to have this enabled for you account. You’ll also need to download the files for the Basic Random Name Selector. The download contains the existing widget (TGZ) and all the files required to create the widget – most of which FrogCode will generate “empty” versions for you. Now that you have the files: open FrogCode Editor click on the Action Cog And choose New. Select Widget and set the name of your widget to be “Random Name – Basic” FrogCode Editor will then create an empty template for you, containing all the files needed to make a widget. Crucially, this widget has its own unique UUID, which is reflected in the code. Make a note of this UUID In the Editor’s file browser, expand assets, then styles. In the corresponding downloaded files, copy the contents of main.css to the Editor version. Note the name in the main.css is ‘Widget.RandomName-Basic’. If the Editor’s main.css had a slightly different name, you’ll need to alter the pasted code to match this. In the Editor’s file browser, new expand views and replace the contents of main.ejs with the downloaded version. And repeat these steps for lang.manifest.json, widget.ejs and widget.js In widget.ejs, the UUID occurs for both the icon (line 2) and the widget title (line 3). Replace these with the UUID you made a note of earlier. (If you have lost this UUID, you can find it widget.manifest.json) In widget.js, replace the UUID on lines 2, 3, 4 and 46 Once you’ve made all these changes, you can save all the files and use the play ▶ button to preview the widget. Things to note: Widget.js is the code for the widget, EJS files are the layout. Manifest files, such as lang.manifest.json contain data which is loaded into the widget. The code in widget.js is commented throughout. Ask questions here if you need help. Main.ejs is the widget displayed live, i.e. when the site is viewed, not in editing mode. It is loaded in on line 64, using this.view(‘main.ejs’); Widget.ejs displays the widget in editing mode (line 152). There is a reference application on your platform, called FrogCode APIs, which contains information about widget preferences etc… When you’re finished with your alterations and you’ve replace the widget icon (download the PSD here), right-click on the widget and choose Deploy. This will send the widget to Package Manager and you can publish it. If you make amendments to the widget, you’ll need to update widget.manifest.json on line 19, adding a new version number. When deploying, Frog will check this number for updates. Once you’re happy with your new random name selector, please post some screenshots to the forum and let us know if you’d like to share the final widget. We can copy it from your platform and post it to the community.
  22. Using Frog with MS Teams View the full article
  23. I've had a couple of schools who have expressed a preference for the assignment wizard to list all the sections one after the other, instead of in tabs. This is possible by adding the following CSS to an HTML widget on the staff dashboard: <style> .frogui_components_wizard, .enforce-order { display: none !important; } .frogui_modules_assignment_wizard_panels_details, .frogui_modules_assignment_wizard_panels_activities, .frogui_modules_assignment_wizard_panels_resources, .frogui_modules_assignment_wizard_panels_assessment { position: relative !important; border-bottom: 5px solid #CCCCCC !important; left: 0px !important; min-height: 550px !important; height: auto !important; } .frogui_modules_assignment_wizard_panels .wrapper { overflow-y: auto !important; overflow-x: hidden !important; } .frogui_assignment_wizard .modal-footer .btn-primary, .frogui_assignment_wizard .modal-footer .btn-default { display: none !important; } </style> After hiding the tab buttons, the CSS forces each section to have a minimum height and stack under each other. They can still expand as you add more activities and resources.
  24. The Leaderboards in FrogPlay are a really simple way to drive engagement, but are often overlooked. Here's a guide about what they show: https://www.frogeducation.com/community/training-play/mini-guides-1/play-leaderboards And yes, you can share the leaderboards in your school. You'll need to contact the service desk for the school code, but when you do, you'll be provided with a web address similar to this: https://www.frogplay.net/leaderboards?id=concept This page initially displays a list of all the commands you can send to the leaderboard. Schools running fixed time competitions can use the from and to dates to control the scores displayed.
  25. I've had a school enquiring about how to display the day number for their timetable (they're looking at operating a 10 day calendar, but wanted to make sure that bank holidays etc didn't disrupt the schedule. I thought about trying to automate the whole thing, but then there's always exceptions, so instead I've prepared a spreadsheet which can be adapted. Dates and Day Numbers.xlsx There's code on the DayNo column to identify weekends: =IF(OR(WEEKDAY(A12)=7,WEEKDAY(A12)=1),"Weekend","") and a second sheet which generates the Javascript Object: ="'"&TEXT('Dates and Day No'!A2,"DD/MM/YYYY")&"':'"&'Dates and Day No'!B2&IF('Dates and Day No'!C2<>""," - "&'Dates and Day No'!C2,"")&"'," Which displays the date in date format (Excel likes to convert this to numbers and then displays the corresponding day and any message, to look something like this: '06/09/2021':'4 - National Coding Week' You can then copy the whole second sheet into this code on an HTML widget: <style> .DatesDaysTable { font-size: 19px; border: 1px solid #CCCCCC; text-align: center; } .DatesDaysTable td, .DatesDaysTable th { padding: 10px; border: 1px solid #CCCCCC; } </style> <table class="DatesDaysTable"> <tr> <th>Day No.</th> </tr> </table> <script> var Dates_Days = { //// PASTE IN HERE /// TO HERE /// DELETE LAST COMMA !! }, today = moment().format('DD/MM/YYYY'), thisHTML = arguments[0]; if (Dates_Days[today]) { thisHTML.find('.DatesDaysTable').append( '<tr>'+ '<td>'+Dates_Days[today]+'</td>'+ '</tr>' ); } </script> The variable today uses in the included moment.js to get today's date in the matching format. thisHTML = arguments[0] targets the HTML widget the code is in. And then it is a simple case to display the appropriate information for the current date.
  • Create New...