<commit_before>import {DocumentAccessRightsDialog} from "../access_rights"
import {addAlert, ContentMenu} from "../../common"

export const menuModel = () => ({
    content: [
        {
            type: 'select-action-dropdown',
            id: 'doc_selector',
            open: false,
            checked: false,
            checkAction: _overview => {
                const checkboxes = document.querySelectorAll('input.entry-select[type=checkbox]')
                checkboxes.forEach(checkbox => checkbox.checked = true)
            },
            uncheckAction: _overview => {
                const checkboxes = document.querySelectorAll('input.entry-select[type=checkbox]')
                checkboxes.forEach(checkbox => checkbox.checked = false)
            },
            content: [
                {
                    title: gettext('Delete selected'),
                    action: overview => {
                        const ids = overview.getSelected()
                        const ownIds = ids.filter(id => overview.documentList.find(doc => doc.id===id).is_owner)
                        if (ownIds.length !== ids.length) {
                            addAlert('error', gettext('You cannot delete documents of other users'))
                        }
                        if (ownIds.length) {
                            overview.mod.actions.deleteDocumentDialog(ownIds)
                        }
                    },
                    order: 0
                },
                {
                    title: gettext('Share selected'),
                    action: overview => {
                        const ids = overview.getSelected()
                        const ownIds = ids.filter(id => overview.documentList.find(doc => doc.id===id).is_owner)
                        if (ownIds.length !== ids.length) {
                            addAlert('error', gettext('You cannot share documents of other users'))
                        }
                        if (ownIds.length) {
                            new DocumentAccessRightsDialog(
                                ids,
                                overview.accessRights,
                                overview.teamMembers,
                                newAccessRights => overview.accessRights = newAccessRights,
                                memberDetails => overview.teamMembers.push(memberDetails)
                            )
                        }
                    },
                    order: 1
                },
                {
                    title: gettext('Copy selected'),
                    action: overview => {
                        const ids = overview.getSelected()
                        if (ids.length) {
                            overview.mod.actions.copyFiles(ids)
                        }
                    },
                    order: 2
                },
                {
                    title: gettext('Export selected as Epub'),
                    action: overview => {
                        const ids = overview.getSelected()
                        if (ids.length) {
                            overview.mod.actions.downloadEpubFiles(ids)
                        }
                    },
                    order: 3
                },
                {
                    title: gettext('Export selected as HTML'),
                    action: overview => {
                        const ids = overview.getSelected()
                        if (ids.length) {
                            overview.mod.actions.downloadHtmlFiles(ids)
                        }
                    },
                    order: 4
                },
                {
                    title: gettext('Export selected as LaTeX'),
                    action: overview => {
                        const ids = overview.getSelected()
                        if (ids.length) {
                            overview.mod.actions.downloadLatexFiles(ids)
                        }
                    },
                    order: 5
                },
                {
                    title: gettext('Download selected as Fidus document'),
                    action: overview => {
                        const ids = overview.getSelected()
                        if (ids.length) {
                            overview.mod.actions.downloadNativeFiles(ids)
                        }
                    },
                    order: 6
                }
            ],
            order: 0
        },
        {
            type: 'button',
            id: 'create-new-document',
            icon: 'plus-circle',
            title: gettext('Create new document'),
            action: overview => {
                if (overview.documentTemplates.length < 2) {
                    window.location.href = '/document/new/'
                } else {
                    const position = document.querySelector('.create-new-document').getBoundingClientRect()
                    const templateMenu = new ContentMenu({
                        menu: {
                            content: overview.documentTemplates.map(docTemplate => ({
                                title: docTemplate.title,
                                action: () => window.location.href = `/document/n${docTemplate.id}/`
                            }))
                        },
                        menuPos: {
                            X: position.right + 5,
                            Y: position.top
                        }
                    })
                    templateMenu.open()
                }
            },
            order: 1
        },
        {
            type: 'button',
            icon: 'upload',
            title: gettext('Upload Fidus document'),
            action: overview => overview.mod.actions.importFidus(),
            order: 2
        },
        {
            type: 'search',
            icon: 'search',
            title: gettext('Search documents'),
            input: (overview, text) => overview.table.search(text),
            order: 3
        }
    ]
})
<commit_msg>quicker new documents<commit_after>import {DocumentAccessRightsDialog} from "../access_rights"
import {addAlert, ContentMenu} from "../../common"

export const menuModel = () => ({
    content: [
        {
            type: 'select-action-dropdown',
            id: 'doc_selector',
            open: false,
            checked: false,
            checkAction: _overview => {
                const checkboxes = document.querySelectorAll('input.entry-select[type=checkbox]')
                checkboxes.forEach(checkbox => checkbox.checked = true)
            },
            uncheckAction: _overview => {
                const checkboxes = document.querySelectorAll('input.entry-select[type=checkbox]')
                checkboxes.forEach(checkbox => checkbox.checked = false)
            },
            content: [
                {
                    title: gettext('Delete selected'),
                    action: overview => {
                        const ids = overview.getSelected()
                        const ownIds = ids.filter(id => overview.documentList.find(doc => doc.id===id).is_owner)
                        if (ownIds.length !== ids.length) {
                            addAlert('error', gettext('You cannot delete documents of other users'))
                        }
                        if (ownIds.length) {
                            overview.mod.actions.deleteDocumentDialog(ownIds)
                        }
                    },
                    order: 0
                },
                {
                    title: gettext('Share selected'),
                    action: overview => {
                        const ids = overview.getSelected()
                        const ownIds = ids.filter(id => overview.documentList.find(doc => doc.id===id).is_owner)
                        if (ownIds.length !== ids.length) {
                            addAlert('error', gettext('You cannot share documents of other users'))
                        }
                        if (ownIds.length) {
                            new DocumentAccessRightsDialog(
                                ids,
                                overview.accessRights,
                                overview.teamMembers,
                                newAccessRights => overview.accessRights = newAccessRights,
                                memberDetails => overview.teamMembers.push(memberDetails)
                            )
                        }
                    },
                    order: 1
                },
                {
                    title: gettext('Copy selected'),
                    action: overview => {
                        const ids = overview.getSelected()
                        if (ids.length) {
                            overview.mod.actions.copyFiles(ids)
                        }
                    },
                    order: 2
                },
                {
                    title: gettext('Export selected as Epub'),
                    action: overview => {
                        const ids = overview.getSelected()
                        if (ids.length) {
                            overview.mod.actions.downloadEpubFiles(ids)
                        }
                    },
                    order: 3
                },
                {
                    title: gettext('Export selected as HTML'),
                    action: overview => {
                        const ids = overview.getSelected()
                        if (ids.length) {
                            overview.mod.actions.downloadHtmlFiles(ids)
                        }
                    },
                    order: 4
                },
                {
                    title: gettext('Export selected as LaTeX'),
                    action: overview => {
                        const ids = overview.getSelected()
                        if (ids.length) {
                            overview.mod.actions.downloadLatexFiles(ids)
                        }
                    },
                    order: 5
                },
                {
                    title: gettext('Download selected as Fidus document'),
                    action: overview => {
                        const ids = overview.getSelected()
                        if (ids.length) {
                            overview.mod.actions.downloadNativeFiles(ids)
                        }
                    },
                    order: 6
                }
            ],
            order: 0
        },
        {
            type: 'button',
            id: 'create-new-document',
            icon: 'plus-circle',
            title: gettext('Create new document'),
            action: overview => {
                if (overview.documentTemplates.length < 2) {
                    overview.app.goTo('/document/new/')
                } else {
                    const position = document.querySelector('.create-new-document').getBoundingClientRect()
                    const templateMenu = new ContentMenu({
                        menu: {
                            content: overview.documentTemplates.map(docTemplate => ({
                                title: docTemplate.title,
                                action: () => overview.app.goTo(`/document/n${docTemplate.id}/`)
                            }))
                        },
                        menuPos: {
                            X: position.right + 5,
                            Y: position.top
                        }
                    })
                    templateMenu.open()
                }
            },
            order: 1
        },
        {
            type: 'button',
            icon: 'upload',
            title: gettext('Upload Fidus document'),
            action: overview => overview.mod.actions.importFidus(),
            order: 2
        },
        {
            type: 'search',
            icon: 'search',
            title: gettext('Search documents'),
            input: (overview, text) => overview.table.search(text),
            order: 3
        }
    ]
})
<|endoftext|>


<commit_before>/** post.js
* @file: /src/app/routes/post.js
* @description: Handles express routing for the POST routes
* @parameters: Object(app), Object(resources)
* @exports: Express routes
*/

var busboy = require('connect-busboy')
var body_parser = require('body-parser')
var urlencodedParser = body_parser.urlencoded({ extended: false })
var fs = require('fs')
var md5 = require('md5')
var getSlug = require('speakingurl')
var ObjectID = require('mongodb').ObjectID

module.exports = function (app, resources) {
  var functions = resources.functions
  var image_processer = resources.image_processer

  app.post('/submit', urlencodedParser, function (req, res, next) {
    var id = req.body.id
    var type = req.body.type
    var hidden = (req.body.hidden) ? true : false;
    var isodate = functions.getISOdate()

    //Prevent speakingurl from converting swedish characters to ae and oe by replacing them with what we want
    //also remove any non alphanumeric characters in url
    var tamperedTitle = String(req.body.title).toLowerCase().replace(/å|ä/g, 'a').replace(/ö/g, 'o').replace(/[^\w\s]/gi, '')
    var niceurl = getSlug(tamperedTitle, {
      // URL Settings
      separator: '-',
      maintainCase: false,
      symbols: false
    })
    var simpleSlug = getSlug(tamperedTitle, {separator: ''})

    var usersdb = resources.collections.users
    var pagesdb = resources.collections.pages
    var revisionsdb = resources.collections.revisions

    usersdb.find({ _id: new ObjectID(req.user._id), "info.blocked": false }).toArray(function(err, result) {
      if(result.length > 0) {
        //Proceed as normal
        if(req.body.cover_image_id == 'undefined' || req.body.cover_image_filename == 'undefined') {
          cover_image_id = null
          cover_image_filename = null
        } else {
          cover_image_id = req.body.cover_image_id
          cover_image_filename = req.body.cover_image_filename
        }

        if(type == 1) { // Fakta
          var data = {
            title: req.body.title,
            url: niceurl,
            type: type,
            post: {
              content: req.body.content,
              sources: {
                  name: typeof(req.body.source_name) === 'string' ? [req.body.source_name] : req.body.source_name,
                  url: typeof(req.body.source_url) === 'string' ? [req.body.source_url] : req.body.source_url,
              },
              type: req.body.type,
              license: req.body.license,
              license_cc_version: req.body.license_cc_version,
              license_holder: req.body.license_holder,
              license_holder_website: req.body.license_holder_website,
              cover: {
                id: cover_image_id,
                filename: cover_image_filename
              }
            }, rating: {
              likes: 0
            }, user_info: {
              id: req.user._id,
              hidden: hidden
            }
          }
        } else if(type == 2) { // Recept
          var data = {
            title: req.body.title,
            url: niceurl,
            type: type,
            post: {
              content: req.body.content,
              sources: {
                  name: typeof(req.body.source_name) === 'string' ? [req.body.source_name] : req.body.source_name,
                  url: typeof(req.body.source_url) === 'string' ? [req.body.source_url] : req.body.source_url,
              },
              food_type: req.body.food_type,
              license: req.body.license,
              license_cc_version: req.body.license_cc_version,
              license_holder: req.body.license_holder,
              license_holder_website: req.body.license_holder_website,
              cover: {
                id: cover_image_id,
                filename: cover_image_filename
              },
              video: req.body.video
            }, rating: {
              likes: 0,
              votes: 0,
              votes_sum: 0
            }, user_info: {
              id: req.user._id,
              hidden: hidden
            }
          }
        } else if(type == 3) { // Restaurang
          var data = {
            title: req.body.title,
            url: niceurl,
            type: type,
            post: {
              content: req.body.content,
              sources: {
                  name: typeof(req.body.source_name) === 'string' ? [req.body.source_name] : req.body.source_name,
                  url: typeof(req.body.source_url) === 'string' ? [req.body.source_url] : req.body.source_url,
              },
              city: req.body.city,
              street: req.body.street,
              coordinates: {
                  latitude: req.body.latitude,
                  longitude: req.body.longitude
              },
              phone: req.body.phone,
              website: req.body.website,
              email: req.body.email,
              license: req.body.license,
              license_cc_version: req.body.license_cc_version,
              license_holder: req.body.license_holder,
              license_holder_website: req.body.license_holder_website,
              veg_offer: req.body.veg_offer,
              food: req.body.food,
              hashtag: req.body.hashtag,
              openhours: {
                monday: req.body.monday,
                tuesday: req.body.tuesday,
                wednesday: req.body.wednesday,
                thursday: req.body.thursday,
                friday: req.body.friday,
                saturday: req.body.saturday,
                sunday: req.body.sunday
              }, cover: {
                id: cover_image_id,
                filename: cover_image_filename
              },
            }, rating: {
                likes: 0,
                votes: 0,
                votes_sum: 0
            }, user_info: {
              id: req.user._id,
              hidden: hidden
            }
          }
        } else if(type == 4) { // Produkt
          var data = {
            title: req.body.title,
            url: niceurl,
            type: type,
            post: {
              content: req.body.content,
              sources: {
                  name: typeof(req.body.source_name) === 'string' ? [req.body.source_name] : req.body.source_name,
                  url: typeof(req.body.source_url) === 'string' ? [req.body.source_url] : req.body.source_url,
              },
              license: req.body.license,
              license_cc_version: req.body.license_cc_version,
              license_holder: req.body.license_holder,
              license_holder_website: req.body.license_holder_website,
              veg_type: req.body.veg_type,
              product_type: req.body.product_type,
              manufacturer: req.body.manufacturer,
              manufacturer_website: req.body.manufacturer_website,
              hashtag: req.body.hashtag,
              cover: {
                id: cover_image_id,
                filename: cover_image_filename
              }
            }, rating: {
              likes: 0,
              votes: 0,
              votes_sum: 0
            }, user_info: {
              id: req.user._id,
              hidden: hidden
            }
          }
        } else if(type == 5) { // Butik
          var data = {
            title: req.body.title,
            url: niceurl,
            type: type,
            post: {
              content: req.body.content,
              sources: {
                  name: typeof(req.body.source_name) === 'string' ? [req.body.source_name] : req.body.source_name,
                  url: typeof(req.body.source_url) === 'string' ? [req.body.source_url] : req.body.source_url,
              },
              license: req.body.license,
              license_cc_version: req.body.license_cc_version,
              license_holder: req.body.license_holder,
              license_holder_website: req.body.license_holder_website,
              city: req.body.city,
              street: req.body.street,
              coordinates: {
                  latitude: req.body.latitude,
                  longitude: req.body.longitude
              },
              website: req.body.website,
              hashtag: req.body.hashtag,
              openhours: {
                monday: req.body.monday,
                tuesday: req.body.tuesday,
                wednesday: req.body.wednesday,
                thursday: req.body.thursday,
                friday: req.body.friday,
                saturday: req.body.saturday,
                sunday: req.body.sunday
              },
              cover: {
                id: cover_image_id,
                filename: cover_image_filename
              }
            }, rating: {
              likes: 0,
              votes: 0,
              votes_sum: 0
            }, user_info: {
              id: req.user._id,
              hidden: hidden
            }
          }
        } else {
          res.redirect('/ny')
        }

        data.accepted = null
        data.slug = simpleSlug

        if(id) {
          id = new ObjectID(id) //If editing the post, the id will be provided as a string and we need to convert it to an objectid
          if('contributors' in data.user_info) {
            //Check if this user has already contributed to the post, otherwise add the user to the array
            var alreadyContributed = false

            for(var userObj in data.user_info.contributors) {
              var userObjId = data.user_info.contributors[userObj].id
              if(req.user._id == userObjId) {
                alreadyContributed = true
              }
            }

            if(!alreadyContributed) {
              data.user_info.contributors.push({
                id: req.user._id,
                hidden: hidden
              })
            }
          }
        } else {
          //This is the first revision, add the user creating it to the list of contributors
          data.user_info.contributors = [{
            id: req.user._id,
            hidden: hidden
          }]
        }

        pagesdb.count({ _id : id }, function(err, count) {
          if(err) throw err
          if(count > 0) {
            //Update
            revisionsdb.find({ post_id : id }).toArray(function(err, result) {
              if(result.length > 0) {
                var revision = result[0]
                revision.modified = isodate //Update date modified
                revision.pending += 1 //Update revisions pending moderation for this post
                revision_number = (new Date(isodate).getTime() / 1000) //This is a unix timestamp
                revision.revisions[revision_number] = data.post

                revision.revisions[revision_number].meta = {
                  accepted: null,
                  user_info: {
                    id: req.user._id,
                    hidden: hidden
                  },
                  timestamp: {
                    created: isodate,
                    updatedby: req.user._id
                  }
                }

                revisionsdb.update({ post_id : id}, revision, function(err, result) {
                  res.redirect('/ny/uppdaterad/?newpost='+niceurl)
                })
              } else {
                console.log('No entry for this page in revisions collection')
                pagesdb.find({ _id : id }).toArray(function(err, result) {
                  data.timestamp = {
                    created: result[0].timestamp.created,
                    update: isodate, // Add timestamp for update
                    updatedby: req.user._id
                  }

                  pagesdb.update({_id:id}, data, function(err, result) {
                    res.redirect('/ny/uppdaterad/?newpost='+niceurl)
                  })
                })
              }
            })
          } else {
            //Insert
            data.timestamp = {}
            data.timestamp.created = isodate // Add timestamp for creation
            pagesdb.insert(data, function(err, doc) {
              if(err) throw err

              var revision_number = (new Date(isodate).getTime() / 1000) //This is a unix timestamp
              var revision = {
                post_id: doc.ops[0]._id,
                pending: 1, //Represents total number of revisions that are awaiting moderation, at insertion, just this one
                modified: isodate,
                revision: revision_number,
                revisions: {},
              }

              revision.revisions[revision_number] = data.post
              revision.revisions[revision_number].meta = {
                accepted: null,
                user_info: data.user_info,
                timestamp: {
                  created: isodate
                }
              }

              revisionsdb.insert(revision, function(err, doc) {
                //Should probably make a redirect to a page showing that the page is updated and will be published after moderation
                res.redirect('/ny/publicerad/?newpost='+niceurl)
              })
            })
          }
        })
      } else {
        //User is blocked, should not be able to send this request in the first place
        next()
      }
    })
  })

  app.post('/submit/file', function(req, res) {
    var fstream
    req.pipe(req.busboy)
    req.busboy.on('file', function (fieldname, file, filename) {
      var imagesdb = resources.collections.images
      imagesdb.count({ }, function (err, num_rows) {
        if (err) throw err
        random = Math.floor((Math.random() * 99999999) + 10000000);
        uHash = md5(num_rows + 1 + random)
        randomsubstring = Math.floor((Math.random() * 20) + 10)
        uFilename = uHash.substring(0, randomsubstring)

        imagesdb.insert({ id:num_rows + 1, filename: uFilename, active: false, deleted: false, "user_info":{ id: req.user._id } }, function(err, doc) {
          if(err) throw err

          var filePath = resources.config.uploads
          var fileNameOriginal = filePath + '/' + uFilename + '_original.jpg'
          fstream = fs.createWriteStream(fileNameOriginal)
          file.pipe(fstream)
          fstream.on('finish', function() {
            var resize = image_processer.resize(uFilename)
            if(resize == true) {
              fstream.on('close', function () {
                res.send(doc.ops[0]._id)
              })
            }
          })
        })
      })
    })
  })

  app.post('/submit/file/avatar', function(req, res) {
  var fstream
  req.pipe(req.busboy)
  req.busboy.on('file', function (fieldname, file, filname) {
    fstream = fs.createWriteStream(resources.config.uploads + '/avatar/' + req.user._id + '_raw.jpg')
    file.pipe(fstream)
    fstream.on('finish', function() {
      var usersdb = resources.collections.users
      var resize = image_processer.avatar(req.user._id)
      if(resize == true) {
        fstream.on('close', function () {
          usersdb.update({
              _id : new ObjectID(req.user._id)
            }, {
            $set: {
              "active_photo": 'vegosvar', // This can be fb or vegosvar, later gr. For easy switching later on
              "vegosvar_photo": '/avatar/' + req.user._id + '.jpg'
            }
            }, function(err, status) {
              if(err) throw err
              res.send(req.user._id)
            })
          })
        }
      })
    })
  })

}<commit_msg>Add cafe type<commit_after>/** post.js
* @file: /src/app/routes/post.js
* @description: Handles express routing for the POST routes
* @parameters: Object(app), Object(resources)
* @exports: Express routes
*/

var busboy = require('connect-busboy')
var body_parser = require('body-parser')
var urlencodedParser = body_parser.urlencoded({ extended: false })
var fs = require('fs')
var md5 = require('md5')
var getSlug = require('speakingurl')
var ObjectID = require('mongodb').ObjectID

module.exports = function (app, resources) {
  var functions = resources.functions
  var image_processer = resources.image_processer

  app.post('/submit', urlencodedParser, function (req, res, next) {
    var id = req.body.id
    var type = req.body.type
    var hidden = (req.body.hidden) ? true : false;
    var isodate = functions.getISOdate()

    //Prevent speakingurl from converting swedish characters to ae and oe by replacing them with what we want
    //also remove any non alphanumeric characters in url
    var tamperedTitle = String(req.body.title).toLowerCase().replace(/å|ä/g, 'a').replace(/ö/g, 'o').replace(/[^\w\s]/gi, '')
    var niceurl = getSlug(tamperedTitle, {
      // URL Settings
      separator: '-',
      maintainCase: false,
      symbols: false
    })
    var simpleSlug = getSlug(tamperedTitle, {separator: ''})

    var usersdb = resources.collections.users
    var pagesdb = resources.collections.pages
    var revisionsdb = resources.collections.revisions

    usersdb.find({ _id: new ObjectID(req.user._id), "info.blocked": false }).toArray(function(err, result) {
      if(result.length > 0) {
        //Proceed as normal
        if(req.body.cover_image_id == 'undefined' || req.body.cover_image_filename == 'undefined') {
          cover_image_id = null
          cover_image_filename = null
        } else {
          cover_image_id = req.body.cover_image_id
          cover_image_filename = req.body.cover_image_filename
        }

        if(type == 1) { // Fakta
          var data = {
            title: req.body.title,
            url: niceurl,
            type: type,
            post: {
              content: req.body.content,
              sources: {
                  name: typeof(req.body.source_name) === 'string' ? [req.body.source_name] : req.body.source_name,
                  url: typeof(req.body.source_url) === 'string' ? [req.body.source_url] : req.body.source_url,
              },
              type: req.body.type,
              license: req.body.license,
              license_cc_version: req.body.license_cc_version,
              license_holder: req.body.license_holder,
              license_holder_website: req.body.license_holder_website,
              cover: {
                id: cover_image_id,
                filename: cover_image_filename
              }
            }, rating: {
              likes: 0
            }, user_info: {
              id: req.user._id,
              hidden: hidden
            }
          }
        } else if(type == 2) { // Recept
          var data = {
            title: req.body.title,
            url: niceurl,
            type: type,
            post: {
              content: req.body.content,
              sources: {
                  name: typeof(req.body.source_name) === 'string' ? [req.body.source_name] : req.body.source_name,
                  url: typeof(req.body.source_url) === 'string' ? [req.body.source_url] : req.body.source_url,
              },
              food_type: req.body.food_type,
              license: req.body.license,
              license_cc_version: req.body.license_cc_version,
              license_holder: req.body.license_holder,
              license_holder_website: req.body.license_holder_website,
              cover: {
                id: cover_image_id,
                filename: cover_image_filename
              },
              video: req.body.video
            }, rating: {
              likes: 0,
              votes: 0,
              votes_sum: 0
            }, user_info: {
              id: req.user._id,
              hidden: hidden
            }
          }
        } else if(type == 3) { // Restaurang
          var data = {
            title: req.body.title,
            url: niceurl,
            type: type,
            post: {
              content: req.body.content,
              sources: {
                  name: typeof(req.body.source_name) === 'string' ? [req.body.source_name] : req.body.source_name,
                  url: typeof(req.body.source_url) === 'string' ? [req.body.source_url] : req.body.source_url,
              },
              city: req.body.city,
              street: req.body.street,
              coordinates: {
                  latitude: req.body.latitude,
                  longitude: req.body.longitude
              },
              phone: req.body.phone,
              website: req.body.website,
              email: req.body.email,
              license: req.body.license,
              license_cc_version: req.body.license_cc_version,
              license_holder: req.body.license_holder,
              license_holder_website: req.body.license_holder_website,
              veg_offer: req.body.veg_offer,
              food: req.body.food,
              hashtag: req.body.hashtag,
              openhours: {
                monday: req.body.monday,
                tuesday: req.body.tuesday,
                wednesday: req.body.wednesday,
                thursday: req.body.thursday,
                friday: req.body.friday,
                saturday: req.body.saturday,
                sunday: req.body.sunday
              }, cover: {
                id: cover_image_id,
                filename: cover_image_filename
              },
            }, rating: {
                likes: 0,
                votes: 0,
                votes_sum: 0
            }, user_info: {
              id: req.user._id,
              hidden: hidden
            }
          }
        } else if(type == 4) { // Produkt
          var data = {
            title: req.body.title,
            url: niceurl,
            type: type,
            post: {
              content: req.body.content,
              sources: {
                  name: typeof(req.body.source_name) === 'string' ? [req.body.source_name] : req.body.source_name,
                  url: typeof(req.body.source_url) === 'string' ? [req.body.source_url] : req.body.source_url,
              },
              license: req.body.license,
              license_cc_version: req.body.license_cc_version,
              license_holder: req.body.license_holder,
              license_holder_website: req.body.license_holder_website,
              veg_type: req.body.veg_type,
              product_type: req.body.product_type,
              manufacturer: req.body.manufacturer,
              manufacturer_website: req.body.manufacturer_website,
              hashtag: req.body.hashtag,
              cover: {
                id: cover_image_id,
                filename: cover_image_filename
              }
            }, rating: {
              likes: 0,
              votes: 0,
              votes_sum: 0
            }, user_info: {
              id: req.user._id,
              hidden: hidden
            }
          }
        } else if(type == 5) { // Butik
          var data = {
            title: req.body.title,
            url: niceurl,
            type: type,
            post: {
              content: req.body.content,
              sources: {
                  name: typeof(req.body.source_name) === 'string' ? [req.body.source_name] : req.body.source_name,
                  url: typeof(req.body.source_url) === 'string' ? [req.body.source_url] : req.body.source_url,
              },
              license: req.body.license,
              license_cc_version: req.body.license_cc_version,
              license_holder: req.body.license_holder,
              license_holder_website: req.body.license_holder_website,
              city: req.body.city,
              street: req.body.street,
              coordinates: {
                  latitude: req.body.latitude,
                  longitude: req.body.longitude
              },
              website: req.body.website,
              hashtag: req.body.hashtag,
              openhours: {
                monday: req.body.monday,
                tuesday: req.body.tuesday,
                wednesday: req.body.wednesday,
                thursday: req.body.thursday,
                friday: req.body.friday,
                saturday: req.body.saturday,
                sunday: req.body.sunday
              },
              cover: {
                id: cover_image_id,
                filename: cover_image_filename
              }
            }, rating: {
              likes: 0,
              votes: 0,
              votes_sum: 0
            }, user_info: {
              id: req.user._id,
              hidden: hidden
            }
          }
        } else if(type == 6) { // Cafe
          var data = {
            title: req.body.title,
            url: niceurl,
            type: type,
            post: {
              content: req.body.content,
              sources: {
                  name: typeof(req.body.source_name) === 'string' ? [req.body.source_name] : req.body.source_name,
                  url: typeof(req.body.source_url) === 'string' ? [req.body.source_url] : req.body.source_url,
              },
              city: req.body.city,
              street: req.body.street,
              coordinates: {
                  latitude: req.body.latitude,
                  longitude: req.body.longitude
              },
              phone: req.body.phone,
              website: req.body.website,
              email: req.body.email,
              license: req.body.license,
              license_cc_version: req.body.license_cc_version,
              license_holder: req.body.license_holder,
              license_holder_website: req.body.license_holder_website,
              veg_offer: req.body.veg_offer,
              food: req.body.food,
              hashtag: req.body.hashtag,
              openhours: {
                monday: req.body.monday,
                tuesday: req.body.tuesday,
                wednesday: req.body.wednesday,
                thursday: req.body.thursday,
                friday: req.body.friday,
                saturday: req.body.saturday,
                sunday: req.body.sunday
              }, cover: {
                id: cover_image_id,
                filename: cover_image_filename
              },
            }, rating: {
                likes: 0,
                votes: 0,
                votes_sum: 0
            }, user_info: {
              id: req.user._id,
              hidden: hidden
            }
          }
        } else {
          res.redirect('/ny')
        }

        data.accepted = null
        data.slug = simpleSlug

        if(id) {
          id = new ObjectID(id) //If editing the post, the id will be provided as a string and we need to convert it to an objectid
          if('contributors' in data.user_info) {
            //Check if this user has already contributed to the post, otherwise add the user to the array
            var alreadyContributed = false

            for(var userObj in data.user_info.contributors) {
              var userObjId = data.user_info.contributors[userObj].id
              if(req.user._id == userObjId) {
                alreadyContributed = true
              }
            }

            if(!alreadyContributed) {
              data.user_info.contributors.push({
                id: req.user._id,
                hidden: hidden
              })
            }
          }
        } else {
          //This is the first revision, add the user creating it to the list of contributors
          data.user_info.contributors = [{
            id: req.user._id,
            hidden: hidden
          }]
        }

        pagesdb.count({ _id : id }, function(err, count) {
          if(err) throw err
          if(count > 0) {
            //Update
            revisionsdb.find({ post_id : id }).toArray(function(err, result) {
              if(result.length > 0) {
                var revision = result[0]
                revision.modified = isodate //Update date modified
                revision.pending += 1 //Update revisions pending moderation for this post
                revision_number = (new Date(isodate).getTime() / 1000) //This is a unix timestamp
                revision.revisions[revision_number] = data.post

                revision.revisions[revision_number].meta = {
                  accepted: null,
                  user_info: {
                    id: req.user._id,
                    hidden: hidden
                  },
                  timestamp: {
                    created: isodate,
                    updatedby: req.user._id
                  }
                }

                revisionsdb.update({ post_id : id}, revision, function(err, result) {
                  res.redirect('/ny/uppdaterad/?newpost='+niceurl)
                })
              } else {
                console.log('No entry for this page in revisions collection')
                pagesdb.find({ _id : id }).toArray(function(err, result) {
                  data.timestamp = {
                    created: result[0].timestamp.created,
                    update: isodate, // Add timestamp for update
                    updatedby: req.user._id
                  }

                  pagesdb.update({_id:id}, data, function(err, result) {
                    res.redirect('/ny/uppdaterad/?newpost='+niceurl)
                  })
                })
              }
            })
          } else {
            //Insert
            data.timestamp = {}
            data.timestamp.created = isodate // Add timestamp for creation
            pagesdb.insert(data, function(err, doc) {
              if(err) throw err

              var revision_number = (new Date(isodate).getTime() / 1000) //This is a unix timestamp
              var revision = {
                post_id: doc.ops[0]._id,
                pending: 1, //Represents total number of revisions that are awaiting moderation, at insertion, just this one
                modified: isodate,
                revision: revision_number,
                revisions: {},
              }

              revision.revisions[revision_number] = data.post
              revision.revisions[revision_number].meta = {
                accepted: null,
                user_info: data.user_info,
                timestamp: {
                  created: isodate
                }
              }

              revisionsdb.insert(revision, function(err, doc) {
                //Should probably make a redirect to a page showing that the page is updated and will be published after moderation
                res.redirect('/ny/publicerad/?newpost='+niceurl)
              })
            })
          }
        })
      } else {
        //User is blocked, should not be able to send this request in the first place
        next()
      }
    })
  })

  app.post('/submit/file', function(req, res) {
    var fstream
    req.pipe(req.busboy)
    req.busboy.on('file', function (fieldname, file, filename) {
      var imagesdb = resources.collections.images
      imagesdb.count({ }, function (err, num_rows) {
        if (err) throw err
        random = Math.floor((Math.random() * 99999999) + 10000000);
        uHash = md5(num_rows + 1 + random)
        randomsubstring = Math.floor((Math.random() * 20) + 10)
        uFilename = uHash.substring(0, randomsubstring)

        imagesdb.insert({ id:num_rows + 1, filename: uFilename, active: false, deleted: false, "user_info":{ id: req.user._id } }, function(err, doc) {
          if(err) throw err

          var filePath = resources.config.uploads
          var fileNameOriginal = filePath + '/' + uFilename + '_original.jpg'
          fstream = fs.createWriteStream(fileNameOriginal)
          file.pipe(fstream)
          fstream.on('finish', function() {
            var resize = image_processer.resize(uFilename)
            if(resize == true) {
              fstream.on('close', function () {
                res.send(doc.ops[0]._id)
              })
            }
          })
        })
      })
    })
  })

  app.post('/submit/file/avatar', function(req, res) {
  var fstream
  req.pipe(req.busboy)
  req.busboy.on('file', function (fieldname, file, filname) {
    fstream = fs.createWriteStream(resources.config.uploads + '/avatar/' + req.user._id + '_raw.jpg')
    file.pipe(fstream)
    fstream.on('finish', function() {
      var usersdb = resources.collections.users
      var resize = image_processer.avatar(req.user._id)
      if(resize == true) {
        fstream.on('close', function () {
          usersdb.update({
              _id : new ObjectID(req.user._id)
            }, {
            $set: {
              "active_photo": 'vegosvar', // This can be fb or vegosvar, later gr. For easy switching later on
              "vegosvar_photo": '/avatar/' + req.user._id + '.jpg'
            }
            }, function(err, status) {
              if(err) throw err
              res.send(req.user._id)
            })
          })
        }
      })
    })
  })

}<|endoftext|>


<commit_before>/* The MIT License (MIT)
 *
 * Copyright (c) 2015 Oliver Bachmann, Karlsruhe, Germany
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
 var xStart = 0;
 var yStart = 0;

/** This is functionality for drawing characters on the canvas using the image map **/
function Codepage(codepageUrl, callback) {
        var COLORS, img, codepageImg;
        var overlay=null;

        function createCanvas(width, height) {

            var newCanvas = document.createElement("canvas");
            newCanvas.setAttribute("width", width);
            newCanvas.setAttribute("height", height);
            //canvasCharacterWidth=Math.floor(width/getDisplayWidth());
            //canvasCharacterHeight=Math.floor(height/getDisplayHeight());
            return newCanvas;
        }

        /*function copyCanvas(source, color, preserveAlpha) {
            var canvas, ctx, imageData, i;
            canvas = createCanvas(source.width, source.height);
            ctx = canvas.getContext("2d");
            ctx.drawImage(source, 0, 0);

            imageData = ctx.getImageData(0, 0, source.width, source.height);
            for (i = 0; i < imageData.data.length; ++i) {
                imageData.data[i++] = COLORS[color][0];
                imageData.data[i++] = COLORS[color][1];
                imageData.data[i++] = COLORS[color][2];
                if (!preserveAlpha) { imageData.data[i] = 255; }
            }
            ctx.putImageData(imageData, 0, 0);
            return canvas;
        }*/

		/** Let's load the image map. See interpreter.js **/
        img = new Image();
        img.onload = function () {
            //var i, background;
            characterWidth = 256/32; //img.width / 32;
            characterHeight = 128/8; // img.height / 8;

            /*codepageImgs = [];
            backgroundImgs = [];
            background = createCanvas(characterWidth, characterHeight);
            for (i = 0; i < COLORS.length; i++) {
                codepageImg = copyCanvas(img, i, true);
                backgroundImg = colorCanvas(background, i, false);
            }*/
            codepageImg=img;

            callback();
        };
        img.src = codepageUrl;

		/** This gets called from modified_write2 from inside escape.js **/
        function drawChar(ctx, asciiCode, foreground, background, x, y, transparent, storeCharacter, storeCharacterX) {

           var realY = y;
           if (typeof(storeCharacter)=="number") {
               realY = storeCharacter;
               storeCharacter=true;
           }
           var realX = x;
           if (typeof(storeCharacterX)=="number") {
               realX = storeCharacterX;
               storeCharacter=true;
           }

            if (x>=xStart-1) { // xStart is the x value of the scrollbar. For example if we show all characters starting at x = 3.
                if (y>=yStart-1) { // yStart is the y value of the scrollbar. For example if we show all characters starting at y > 5.

						// transparent is only used in conjunction to redraw the cursor. So this is nearly always true - but anyway it might not get called.
                        if ( (typeof(transparent)=="undefined") || (transparent==false) ) {
                         var charArray = Array();

                         charArray[0]=asciiCode;
                         charArray[1]=foreground;
                         charArray[2]=background;

							// This are checks, otherwise the browser hangs. If it's more efficient to do a try catch then that's okay too.
                            if (typeof(screenCharacterArray[realY])=="undefined") {
                                screenCharacterArray[realY]=new Array();
                                totalVisibleHeight=realY;
                                height=realY;
                                screenCharacterArray[realY][realX]=charArray;

                                //console.log("Array "+realY);

                            } else
                            if ( (typeof(storeCharacter)=="undefined") || (storeCharacter==true) ) {
                                screenCharacterArray[realY][realX]=charArray;
                                //console.log("Array 2 "+realY+" "+realX);
                            }
                        }

						 // I don't remember what this is good for. Maybe search for it?
                         if (this.overlay!=null) {
                                    asciiCode=this.overlay[0];
                                    foreground=this.overlay[1];
                                    background=this.overlay[2];
                                }

						// This calculates the real X coordinates on the canvas
                        x = (x  ) * parseInt(canvasCharacterWidth);

						// This calculates the real Y coordinates on the canvas
                        y = (y ) * parseInt( canvasCharacterHeight );

						// Again a check, used in conjunction with redrawing the cursor. Or maybe something else. Especially when it's about NOT drawing the background color.
                        if ( (typeof(transparent)=="undefined") || (transparent==false) ) {

							// This now calculates the position of the character on the image.
                            var xpos=background;

                            while (xpos >= 16) xpos=xpos-16;
                            // This calculates the position of the block of the image, which has the same characters over and over again with different backgrounds, regarding the y position
                            //console.log(Math.random()+"background:"+background);
                            var ypos = Math.floor(background/16);
                            ///console.log(Math.random()+"ypos:"+ypos);

                            var myasciiCode=219;

                            var myx = (myasciiCode % 32) * characterWidth+(xpos*256);
                            var myy = Math.floor(myasciiCode / 32) * characterHeight + (ypos*128);

						    // Then the character from the image gets copied to the canvas
                            //alert("1:myx="+myx+" myy="+myy+" x="+x+" y="+y+"CW1:"+characterHeight+" canvasCharacterHeight:"+canvasCharacterHeight);
                            ctx.drawImage(codepageImg, myx, myy, characterWidth, characterHeight, x, y, canvasCharacterWidth, canvasCharacterHeight);
                        }

						// Now this gets always called!
                        var xpos=foreground;
                        while (xpos >= 16) xpos=xpos-16;
                        var ypos = Math.floor(foreground/16);

                        var myx = (asciiCode % 32) * characterWidth+(xpos*256);
                        var myy = Math.floor(asciiCode / 32) * characterHeight + (ypos*128);
                        //alert(myx+"/"+x);
						// As you can see, the calculated character from the image gets copied/drawn to the canvas
                        ctx.drawImage(codepageImg, myx, myy, characterWidth, characterHeight, x, y, canvasCharacterWidth, canvasCharacterHeight);
            } // if x >= xStart-1
            } // if y >= yStart-1
			// Now here you should place code which stores characters in the screenCharacterArray in case characters get rendered that are above or before the start of the scrollbar. Is this ever the case?
			// I'm not sure. Mabye this is never the case :)
        }

		 // This gets called inside doRedraw inside requestanimframe.js, don't ask me where doRedraw=true is set.
         function copyChar(ctx, originX, originY, x, y) {

           // This is just some information used when scrolling is implemented
            if (x>=xStart-1) {
                if (y>=yStart-1) {

						// Get the character from the array
						if (typeof(screenCharacterArray[originY])=="undefined") return;
						if (typeof(screenCharacterArray[originY][originX])=="undefined") return;
                        var charArray = screenCharacterArray[originY][originX];
						// This is how we read the properties of the specified character at x and y position

                        asciiCode=charArray[0];
                        foreground=charArray[1];
                        background=charArray[2];

						/** This again gets converted to real canvas coordinates **/
                        x = (x  ) * parseInt(canvasCharacterWidth);
                        y = (y ) * parseInt( canvasCharacterHeight );

							// First we set the background color
                            var xpos=background;

                            while (xpos >= 16) xpos=xpos-16;
                            // This calculates the position of the block of the image, which has the same characters over and over again with different backgrounds, regarding the y position
                            //console.log(Math.random()+"background:"+background);
                            var ypos = Math.floor(background/16);
                            ///console.log(Math.random()+"ypos:"+ypos);

                            var myasciiCode=219;

                            var myx = (myasciiCode % 32) * characterWidth+(xpos*256);
                            var myy = Math.floor(myasciiCode / 32) * characterHeight + (ypos*128);

                            //alert("1:myx="+myx+" myy="+myy+" x="+x+" y="+y+"CW1:"+characterHeight+" canvasCharacterHeight:"+canvasCharacterHeight);
                            ctx.drawImage(codepageImg, myx, myy, characterWidth, characterHeight, x, y, canvasCharacterWidth, canvasCharacterHeight);

                        // Then we do everything that has to do with the foreground color
                        var xpos=foreground;
                        while (xpos >= 16) xpos=xpos-16;
                        var ypos = Math.floor(foreground/16);

                        var myx = (asciiCode % 32) * characterWidth+(xpos*256);
                        var myy = Math.floor(asciiCode / 32) * characterHeight + (ypos*128);
                        //alert(myx+"/"+x);
                        ctx.drawImage(codepageImg, myx, myy, characterWidth, characterHeight, x, y, canvasCharacterWidth, canvasCharacterHeight);
            }
            }
        };

        /** Creates an own instance of a canvas object with its own context **/
        function generateDisplay(width, height) {
            return createCanvas(fullCanvasWidth, fullCanvasHeight);
        }

		/** Currently this is not getting called, but it could get used from codepagedisplay.js 309 if needed. Maybe this needs to get implemented differently to make scrolling more smoothly or at different occasions **/
        function scrollDisplay(ctx, canvas) {
            ctx.drawImage(canvas, 0, characterHeight, canvas.width, canvas.height - characterHeight * 2, 0, 0, canvas.width, canvas.height - characterHeight * 2);
            ctx.fillStyle = "black";
            ctx.fillRect(0, canvas.height - characterHeight * 2, canvas.width, characterHeight);
        }

        return { "drawChar": drawChar, "generateDisplay": generateDisplay, "scrollDisplay": scrollDisplay, "copyChar" : copyChar };
    };

    /** This class Display. Still needed? This should get checked. If it gets called at a all.
	    It was mostly used by another parser. Or it is still getting used by other projects. However, since escape.js is implemented we don't need most of this. Anyhow,
	    somehow this has own instances of x and y coordinates - still needed? There's for example also a cursorPosX and cursorPosY variable. If you can easily remove this, do this **/
    function Display() {
        var canvas, ctx, x, y, savedX, savedY, foreground, background, bold, inverse;

        canvas = codepage.generateDisplay(width, height);

		// Maybe you can get the context also using display.ctx
        ctx = canvas.getContext("2d");

		// Call this to set the current cursor position to x = 0 and y = 0
        function homeCursor() {
            x = 0;
            y = 0;
        }

		// Simple getter
		function getPosX() {
			return x;
		}

		// Simple getter
		function getPosY() {
				return y;
		}

        function resetAttributes() {
            foreground = 7;
            background = 0;
            bold = false;
            inverse = false;
        }

        function setBold(value) {
            bold = value;
        }

        function setInverse(value) {
            inverse = value;
        }

        function setPos(newX, newY) {
            x = Math.min(width, Math.max(0, newX));
            y = Math.min(height, Math.max(0, newY));
        }

        function setForeground(value) {
            foreground = value;
        }

        function setBackground(value) {
            background = value;
        }

        function clearToEndOfLine() {
            var i;
            for (i = x; i < width; ++i) {
                codepage.drawChar(ctx, 0, 0, 0, i, y);
            }
        }

       function clearScreen(fillStyle) {
            if (typeof(fillStyle)=="undefined") fillStyle="black";
            homeCursor();
            ctx.fillStyle = fillStyle;
            ctx.fillRect(0, 0, canvas.width, canvas.height);
        }

        function up(num) {
            y = Math.max(1, y - num);
        }

        function down(num) {
            y = Math.min(height - 1, y + num);
        }

        function newLine() {
            x = 0;
            if (y === height - 1) {
				// This is commented out. Does it need to get activated again? Maybe do something different, like updating the scrollbars also?
                //codepage.scrollDisplay(ctx, canvas);
                return true;
            }
            ++y;
            return false;
        }

        function back(num) {
            x = Math.max(1, x - num);
        }

        function forward(num) {
            if (x === width) { newLine(); }
            x = Math.min(width, x + num);
        }

		// Big question is this needed, now that we already have a drawChar function in here.
        function drawChar(asciiCode) {

            switch (asciiCode) {
            case 26:
                break;
            default:
                if (!inverse) {
                    //alert("calling drawChar with ascii:"+asciiCode+"fg:"+foreground+" background:"+background+"x:"+x+"y:"+y);;
                    codepage.drawChar(ctx, asciiCode, bold ? foreground  : foreground, background, x++, y);

                } else {
                    //alert("inv ascii:"+asciiCode+"fg:"+foreground+" background:"+background);
                    //alert("calling drawChar with ascii:"+asciiCode+"fg:"+foreground+" background:"+background+"x:"+x+"y:"+y);;

                    codepage.drawChar(ctx, asciiCode, bold ? background + 8 : background, foreground, x++, y);
                }
                if (x === width + 1) { return newLine(); }
            }
            return false;
        }

        function savePosition() {
            savedX = x;
            savedY = y;
        }

        function restorePosition() {
            x = savedX;
            y = savedY;
        }

        homeCursor();
        resetAttributes();

        return {
            "resetAttributes": resetAttributes,
            "setBold": setBold,
            "setInverse": setInverse,
            "setPos": setPos,
            "up": up,
            "down": down,
            "newLine": newLine,
            "back": back,
            "forward": forward,
            "setForeground": setForeground,
            "setBackground": setBackground,
            "clearToEndOfLine": clearToEndOfLine,
            "clearScreen": clearScreen,
            "canvas": canvas,
            "drawChar": drawChar,
            "savePosition": savePosition,
            "restorePosition": restorePosition,
            "getPosX": getPosX,
            "getPosY": getPosY
        };
    }
<commit_msg>Only drawing visible area<commit_after>/* The MIT License (MIT)
 *
 * Copyright (c) 2015 Oliver Bachmann, Karlsruhe, Germany
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
 var xStart = 0;
 var yStart = 0;

/** This is functionality for drawing characters on the canvas using the image map **/
function Codepage(codepageUrl, callback) {
        var COLORS, img, codepageImg;
        var overlay=null;

        function createCanvas(width, height) {

            var newCanvas = document.createElement("canvas");
            newCanvas.setAttribute("width", width);
            newCanvas.setAttribute("height", height);
            //canvasCharacterWidth=Math.floor(width/getDisplayWidth());
            //canvasCharacterHeight=Math.floor(height/getDisplayHeight());
            return newCanvas;
        }

        /*function copyCanvas(source, color, preserveAlpha) {
            var canvas, ctx, imageData, i;
            canvas = createCanvas(source.width, source.height);
            ctx = canvas.getContext("2d");
            ctx.drawImage(source, 0, 0);

            imageData = ctx.getImageData(0, 0, source.width, source.height);
            for (i = 0; i < imageData.data.length; ++i) {
                imageData.data[i++] = COLORS[color][0];
                imageData.data[i++] = COLORS[color][1];
                imageData.data[i++] = COLORS[color][2];
                if (!preserveAlpha) { imageData.data[i] = 255; }
            }
            ctx.putImageData(imageData, 0, 0);
            return canvas;
        }*/

		/** Let's load the image map. See interpreter.js **/
        img = new Image();
        img.onload = function () {
            //var i, background;
            characterWidth = 256/32; //img.width / 32;
            characterHeight = 128/8; // img.height / 8;

            /*codepageImgs = [];
            backgroundImgs = [];
            background = createCanvas(characterWidth, characterHeight);
            for (i = 0; i < COLORS.length; i++) {
                codepageImg = copyCanvas(img, i, true);
                backgroundImg = colorCanvas(background, i, false);
            }*/
            codepageImg=img;

            callback();
        };
        img.src = codepageUrl;

		/** This gets called from modified_write2 from inside escape.js **/
        function drawChar(ctx, asciiCode, foreground, background, x, y, transparent, storeCharacter, storeCharacterX) {

           var realY = y;
           if (typeof(storeCharacter)=="number") {
               realY = storeCharacter;
               storeCharacter=true;
           }
           var realX = x;
           if (typeof(storeCharacterX)=="number") {
               realX = storeCharacterX;
               storeCharacter=true;
           }

            if (x>=xStart-1) { // xStart is the x value of the scrollbar. For example if we show all characters starting at x = 3.
                if (y>=yStart-1) { // yStart is the y value of the scrollbar. For example if we show all characters starting at y > 5.

						// transparent is only used in conjunction to redraw the cursor. So this is nearly always true - but anyway it might not get called.
                        if ( (typeof(transparent)=="undefined") || (transparent==false) ) {
                         var charArray = Array();

                         charArray[0]=asciiCode;
                         charArray[1]=foreground;
                         charArray[2]=background;

							// This are checks, otherwise the browser hangs. If it's more efficient to do a try catch then that's okay too.
                            if (typeof(screenCharacterArray[realY])=="undefined") {
                                screenCharacterArray[realY]=new Array();
                                totalVisibleHeight=realY;
                                height=realY;
                                screenCharacterArray[realY][realX]=charArray;

                                //console.log("Array "+realY);

                            } else
                            if ( (typeof(storeCharacter)=="undefined") || (storeCharacter==true) ) {
                                screenCharacterArray[realY][realX]=charArray;
                                //console.log("Array 2 "+realY+" "+realX);
                            }
                        }

						 // I don't remember what this is good for. Maybe search for it?
                         if (this.overlay!=null) {
                                    asciiCode=this.overlay[0];
                                    foreground=this.overlay[1];
                                    background=this.overlay[2];
                                }

						// This calculates the real X coordinates on the canvas
                        x = (x  ) * parseInt(canvasCharacterWidth);

						// This calculates the real Y coordinates on the canvas
                        y = (y ) * parseInt( canvasCharacterHeight );

						// Again a check, used in conjunction with redrawing the cursor. Or maybe something else. Especially when it's about NOT drawing the background color.
                        if ( (typeof(transparent)=="undefined") || (transparent==false) ) {

							// This now calculates the position of the character on the image.
                            var xpos=background;

                            while (xpos >= 16) xpos=xpos-16;
                            // This calculates the position of the block of the image, which has the same characters over and over again with different backgrounds, regarding the y position
                            //console.log(Math.random()+"background:"+background);
                            var ypos = Math.floor(background/16);
                            ///console.log(Math.random()+"ypos:"+ypos);

                            var myasciiCode=219;

                            var myx = (myasciiCode % 32) * characterWidth+(xpos*256);
                            var myy = Math.floor(myasciiCode / 32) * characterHeight + (ypos*128);

                           if (realY < visibleHeight) {

						    	// Then the character from the image gets copied to the canvas
                            	//alert("1:myx="+myx+" myy="+myy+" x="+x+" y="+y+"CW1:"+characterHeight+" canvasCharacterHeight:"+canvasCharacterHeight);
                            	ctx.drawImage(codepageImg, myx, myy, characterWidth, characterHeight, x, y, canvasCharacterWidth, canvasCharacterHeight);
                            }
                        }

						// Now this gets always called!
                        var xpos=foreground;
                        while (xpos >= 16) xpos=xpos-16;
                        var ypos = Math.floor(foreground/16);

                        var myx = (asciiCode % 32) * characterWidth+(xpos*256);
                        var myy = Math.floor(asciiCode / 32) * characterHeight + (ypos*128);
                        //alert(myx+"/"+x);
						// As you can see, the calculated character from the image gets copied/drawn to the canvas
                        ctx.drawImage(codepageImg, myx, myy, characterWidth, characterHeight, x, y, canvasCharacterWidth, canvasCharacterHeight);
            } // if x >= xStart-1
            } // if y >= yStart-1
			// Now here you should place code which stores characters in the screenCharacterArray in case characters get rendered that are above or before the start of the scrollbar. Is this ever the case?
			// I'm not sure. Mabye this is never the case :)
        }

		 // This gets called inside doRedraw inside requestanimframe.js, don't ask me where doRedraw=true is set.
         function copyChar(ctx, originX, originY, x, y) {

           // This is just some information used when scrolling is implemented
            if (x>=xStart-1) {
                if (y>=yStart-1) {

						// Get the character from the array
						if (typeof(screenCharacterArray[originY])=="undefined") return;
						if (typeof(screenCharacterArray[originY][originX])=="undefined") return;
                        var charArray = screenCharacterArray[originY][originX];
						// This is how we read the properties of the specified character at x and y position

                        asciiCode=charArray[0];
                        foreground=charArray[1];
                        background=charArray[2];

						/** This again gets converted to real canvas coordinates **/
                        x = (x  ) * parseInt(canvasCharacterWidth);
                        y = (y ) * parseInt( canvasCharacterHeight );

							// First we set the background color
                            var xpos=background;

                            while (xpos >= 16) xpos=xpos-16;
                            // This calculates the position of the block of the image, which has the same characters over and over again with different backgrounds, regarding the y position
                            //console.log(Math.random()+"background:"+background);
                            var ypos = Math.floor(background/16);
                            ///console.log(Math.random()+"ypos:"+ypos);

                            var myasciiCode=219;

                            var myx = (myasciiCode % 32) * characterWidth+(xpos*256);
                            var myy = Math.floor(myasciiCode / 32) * characterHeight + (ypos*128);

                            //alert("1:myx="+myx+" myy="+myy+" x="+x+" y="+y+"CW1:"+characterHeight+" canvasCharacterHeight:"+canvasCharacterHeight);
                            ctx.drawImage(codepageImg, myx, myy, characterWidth, characterHeight, x, y, canvasCharacterWidth, canvasCharacterHeight);

                        // Then we do everything that has to do with the foreground color
                        var xpos=foreground;
                        while (xpos >= 16) xpos=xpos-16;
                        var ypos = Math.floor(foreground/16);

                        var myx = (asciiCode % 32) * characterWidth+(xpos*256);
                        var myy = Math.floor(asciiCode / 32) * characterHeight + (ypos*128);
                        //alert(myx+"/"+x);
                        ctx.drawImage(codepageImg, myx, myy, characterWidth, characterHeight, x, y, canvasCharacterWidth, canvasCharacterHeight);
            }
            }
        };

        /** Creates an own instance of a canvas object with its own context **/
        function generateDisplay(width, height) {
            return createCanvas(fullCanvasWidth, fullCanvasHeight);
        }

		/** Currently this is not getting called, but it could get used from codepagedisplay.js 309 if needed. Maybe this needs to get implemented differently to make scrolling more smoothly or at different occasions **/
        function scrollDisplay(ctx, canvas) {
            ctx.drawImage(canvas, 0, characterHeight, canvas.width, canvas.height - characterHeight * 2, 0, 0, canvas.width, canvas.height - characterHeight * 2);
            ctx.fillStyle = "black";
            ctx.fillRect(0, canvas.height - characterHeight * 2, canvas.width, characterHeight);
        }

        return { "drawChar": drawChar, "generateDisplay": generateDisplay, "scrollDisplay": scrollDisplay, "copyChar" : copyChar };
    };

    /** This class Display. Still needed? This should get checked. If it gets called at a all.
	    It was mostly used by another parser. Or it is still getting used by other projects. However, since escape.js is implemented we don't need most of this. Anyhow,
	    somehow this has own instances of x and y coordinates - still needed? There's for example also a cursorPosX and cursorPosY variable. If you can easily remove this, do this **/
    function Display() {
        var canvas, ctx, x, y, savedX, savedY, foreground, background, bold, inverse;

        canvas = codepage.generateDisplay(width, height);

		// Maybe you can get the context also using display.ctx
        ctx = canvas.getContext("2d");

		// Call this to set the current cursor position to x = 0 and y = 0
        function homeCursor() {
            x = 0;
            y = 0;
        }

		// Simple getter
		function getPosX() {
			return x;
		}

		// Simple getter
		function getPosY() {
				return y;
		}

        function resetAttributes() {
            foreground = 7;
            background = 0;
            bold = false;
            inverse = false;
        }

        function setBold(value) {
            bold = value;
        }

        function setInverse(value) {
            inverse = value;
        }

        function setPos(newX, newY) {
            x = Math.min(width, Math.max(0, newX));
            y = Math.min(height, Math.max(0, newY));
        }

        function setForeground(value) {
            foreground = value;
        }

        function setBackground(value) {
            background = value;
        }

        function clearToEndOfLine() {
            var i;
            for (i = x; i < width; ++i) {
                codepage.drawChar(ctx, 0, 0, 0, i, y);
            }
        }

       function clearScreen(fillStyle) {
            if (typeof(fillStyle)=="undefined") fillStyle="black";
            homeCursor();
            ctx.fillStyle = fillStyle;
            ctx.fillRect(0, 0, canvas.width, canvas.height);
        }

        function up(num) {
            y = Math.max(1, y - num);
        }

        function down(num) {
            y = Math.min(height - 1, y + num);
        }

        function newLine() {
            x = 0;
            if (y === height - 1) {
				// This is commented out. Does it need to get activated again? Maybe do something different, like updating the scrollbars also?
                //codepage.scrollDisplay(ctx, canvas);
                return true;
            }
            ++y;
            return false;
        }

        function back(num) {
            x = Math.max(1, x - num);
        }

        function forward(num) {
            if (x === width) { newLine(); }
            x = Math.min(width, x + num);
        }

		// Big question is this needed, now that we already have a drawChar function in here.
        function drawChar(asciiCode) {

            switch (asciiCode) {
            case 26:
                break;
            default:
                if (!inverse) {
                    //alert("calling drawChar with ascii:"+asciiCode+"fg:"+foreground+" background:"+background+"x:"+x+"y:"+y);;
                    codepage.drawChar(ctx, asciiCode, bold ? foreground  : foreground, background, x++, y);

                } else {
                    //alert("inv ascii:"+asciiCode+"fg:"+foreground+" background:"+background);
                    //alert("calling drawChar with ascii:"+asciiCode+"fg:"+foreground+" background:"+background+"x:"+x+"y:"+y);;

                    codepage.drawChar(ctx, asciiCode, bold ? background + 8 : background, foreground, x++, y);
                }
                if (x === width + 1) { return newLine(); }
            }
            return false;
        }

        function savePosition() {
            savedX = x;
            savedY = y;
        }

        function restorePosition() {
            x = savedX;
            y = savedY;
        }

        homeCursor();
        resetAttributes();

        return {
            "resetAttributes": resetAttributes,
            "setBold": setBold,
            "setInverse": setInverse,
            "setPos": setPos,
            "up": up,
            "down": down,
            "newLine": newLine,
            "back": back,
            "forward": forward,
            "setForeground": setForeground,
            "setBackground": setBackground,
            "clearToEndOfLine": clearToEndOfLine,
            "clearScreen": clearScreen,
            "canvas": canvas,
            "drawChar": drawChar,
            "savePosition": savePosition,
            "restorePosition": restorePosition,
            "getPosX": getPosX,
            "getPosY": getPosY
        };
    }
<|endoftext|>


<commit_before>import Cookies from 'js-cookie'
import {Notification} from 'element-ui'

const util = {}

/**
 * 设置页面title
 */
util.title = function (title) {
  if (title) {
    title = 'ESS | ' + title
  } else {
    title = 'ESS | 在线考试支持系统'
  }

  window.document.title = title
}

/**
 * 获取cookie内容
 * @param name cookie名称
 * @returns 对应数据, 若为json类型数据, 返回转换后的对象
 */
util.getCookie = function (name) {
  let data = Cookies.get(name)

  try {
    data = JSON.parse(data)
  } catch (e) {
    // do nothing
  }

  return data
}

/**
 * 存储cookie, cookie 过期时间统一设置为 1 天
 * @param name cookie名称
 * @param data 对应数据
 */
util.setCookie = function (name, data) {
  if (navigator.cookieEnabled) {
    Cookies.set(name, data, {expires: 1})
  } else {
    util.notifyError('请打开浏览器Cookie')
  }
}

/**
 * 移除cookie
 * @param name cookie名称
 */
util.removeCookie = function (name) {
  Cookies.remove(name)
}

/**
 * 成功通知
 * @param message 成功信息
 */
util.notifySuccess = function (message) {
  Notification.success({
    title: '成功',
    message: message
  })
}

/**
 * 错误通知
 * @param message 错误信息
 */
util.notifyError = function (message) {
  Notification.error({
    title: '错误',
    message: message
  })
}

/**
 * 校验邮箱合法性
 */
util.validateEmail = (rule, value, callback) => {
  const mailRegex = /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+\.){1,63}[a-z0-9]+$/

  if (value === '') {
    callback(new Error('请输入邮箱'))
  } else if (!mailRegex.test(value)) {
    callback(new Error('请输入正确邮箱'))
  } else {
    callback()
  }
}

export default util
<commit_msg>feature: add getParamByName from url into util.js<commit_after>import Cookies from 'js-cookie'
import {Notification} from 'element-ui'

const util = {}

/**
 * 设置页面title
 */
util.title = function (title) {
  if (title) {
    title = 'ESS | ' + title
  } else {
    title = 'ESS | 在线考试支持系统'
  }

  window.document.title = title
}

/**
 * 获取cookie内容
 * @param name cookie名称
 * @returns 对应数据, 若为json类型数据, 返回转换后的对象
 */
util.getCookie = function (name) {
  let data = Cookies.get(name)

  try {
    data = JSON.parse(data)
  } catch (e) {
    // do nothing
  }

  return data
}

/**
 * 存储cookie, cookie 过期时间统一设置为 1 天
 * @param name cookie名称
 * @param data 对应数据
 */
util.setCookie = function (name, data) {
  if (navigator.cookieEnabled) {
    Cookies.set(name, data, {expires: 1})
  } else {
    util.notifyError('请打开浏览器Cookie')
  }
}

/**
 * 移除cookie
 * @param name cookie名称
 */
util.removeCookie = function (name) {
  Cookies.remove(name)
}

/**
 * 成功通知
 * @param message 成功信息
 */
util.notifySuccess = function (message) {
  Notification.success({
    title: '成功',
    message: message
  })
}

/**
 * 错误通知
 * @param message 错误信息
 */
util.notifyError = function (message) {
  Notification.error({
    title: '错误',
    message: message
  })
}

/**
 * 校验邮箱合法性
 */
util.validateEmail = (rule, value, callback) => {
  const mailRegex = /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+\.){1,63}[a-z0-9]+$/

  if (value === '') {
    callback(new Error('请输入邮箱'))
  } else if (!mailRegex.test(value)) {
    callback(new Error('请输入正确邮箱'))
  } else {
    callback()
  }
}

/**
 * 根据参数名称获取url中的参数
 */
util.getParamByName = function (name) {
  let url = window.location.href
  name = name.replace(/[\[\]]/g, '\\$&')
  let regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
    results = regex.exec(url)
  if (!results) return null
  if (!results[2]) return ''
  return decodeURIComponent(results[2].replace(/\+/g, ' '))
}

export default util
<|endoftext|>