diff --git a/Gemfile b/Gemfile index 231984a5..7da812cc 100644 --- a/Gemfile +++ b/Gemfile @@ -59,6 +59,12 @@ gem 'jquery-datatables-rails', '~> 2.2.1' # for user avatars gem 'gravtastic' +# for maps +gem 'leaflet-rails', '~> 0.7.4' + +# for country selects +gem 'country_select', github: 'stefanpenner/country_select' + # for upload management gem 'paperclip' diff --git a/Gemfile.lock b/Gemfile.lock index 4458010b..37423292 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,10 @@ +GIT + remote: git://github.com/stefanpenner/country_select.git + revision: 585e9538a01ae9878e92f12a98261a09842ed015 + specs: + country_select (2.1.0) + countries (~> 0.9, >= 0.9.3) + GEM remote: https://rubygems.org/ specs: @@ -59,7 +66,7 @@ GEM axlsx (>= 2.0.1) rails (>= 3.1) bcrypt (3.1.7) - bootstrap-sass (3.1.1.1) + bootstrap-sass (3.3.1.0) sass (~> 3.2) bootstrap3-datetimepicker-rails (3.0.3) momentjs-rails (>= 2.8.1) @@ -98,12 +105,15 @@ GEM execjs coffee-script-source (1.7.0) columnize (0.8.9) + countries (0.9.3) + currencies (~> 0.4.2) coveralls (0.7.0) multi_json (~> 1.3) rest-client simplecov (>= 0.7) term-ansicolor thor + currencies (0.4.2) d3_rails (3.4.6) railties (>= 3.1.0) daemons (1.1.9) @@ -178,6 +188,7 @@ GEM jwt (1.0.0) launchy (2.4.2) addressable (~> 2.3) + leaflet-rails (0.7.4) letter_opener (1.2.0) launchy (~> 2.2) listen (2.7.2) @@ -430,6 +441,7 @@ DEPENDENCIES capybara chart-js-rails cocoon + country_select! coveralls d3_rails daemons @@ -447,6 +459,7 @@ DEPENDENCIES hoptoad_notifier (~> 2.3) jquery-datatables-rails (~> 2.2.1) jquery-rails + leaflet-rails (~> 0.7.4) letter_opener mina momentjs-rails (>= 2.8.1) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index d78e69ec..b81e82d5 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -22,10 +22,13 @@ //= require dashboard //= require ahoy //= require smoothscroll +//= require trianglify.min +//= require tinycolor //= require bootstrap-markdown //= require to-markdown //= require markdown //= require moment +//= require leaflet //= require bootstrap-datetimepicker //= require osem-datepickers //= require osem-datatables diff --git a/app/assets/javascripts/tinycolor.js b/app/assets/javascripts/tinycolor.js new file mode 100644 index 00000000..d7ff1131 --- /dev/null +++ b/app/assets/javascripts/tinycolor.js @@ -0,0 +1,1112 @@ +// TinyColor v1.1.0 +// https://github.com/bgrins/TinyColor +// Brian Grinstead, MIT License + +(function() { + +var trimLeft = /^[\s,#]+/, + trimRight = /\s+$/, + tinyCounter = 0, + math = Math, + mathRound = math.round, + mathMin = math.min, + mathMax = math.max, + mathRandom = math.random; + +var tinycolor = function tinycolor (color, opts) { + + color = (color) ? color : ''; + opts = opts || { }; + + // If input is already a tinycolor, return itself + if (color instanceof tinycolor) { + return color; + } + // If we are called as a function, call using new instead + if (!(this instanceof tinycolor)) { + return new tinycolor(color, opts); + } + + var rgb = inputToRGB(color); + this._originalInput = color, + this._r = rgb.r, + this._g = rgb.g, + this._b = rgb.b, + this._a = rgb.a, + this._roundA = mathRound(100*this._a) / 100, + this._format = opts.format || rgb.format; + this._gradientType = opts.gradientType; + + // Don't let the range of [0,255] come back in [0,1]. + // Potentially lose a little bit of precision here, but will fix issues where + // .5 gets interpreted as half of the total, instead of half of 1 + // If it was supposed to be 128, this was already taken care of by `inputToRgb` + if (this._r < 1) { this._r = mathRound(this._r); } + if (this._g < 1) { this._g = mathRound(this._g); } + if (this._b < 1) { this._b = mathRound(this._b); } + + this._ok = rgb.ok; + this._tc_id = tinyCounter++; +}; + +tinycolor.prototype = { + isDark: function() { + return this.getBrightness() < 128; + }, + isLight: function() { + return !this.isDark(); + }, + isValid: function() { + return this._ok; + }, + getOriginalInput: function() { + return this._originalInput; + }, + getFormat: function() { + return this._format; + }, + getAlpha: function() { + return this._a; + }, + getBrightness: function() { + var rgb = this.toRgb(); + return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000; + }, + setAlpha: function(value) { + this._a = boundAlpha(value); + this._roundA = mathRound(100*this._a) / 100; + return this; + }, + toHsv: function() { + var hsv = rgbToHsv(this._r, this._g, this._b); + return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a }; + }, + toHsvString: function() { + var hsv = rgbToHsv(this._r, this._g, this._b); + var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100); + return (this._a == 1) ? + "hsv(" + h + ", " + s + "%, " + v + "%)" : + "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")"; + }, + toHsl: function() { + var hsl = rgbToHsl(this._r, this._g, this._b); + return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a }; + }, + toHslString: function() { + var hsl = rgbToHsl(this._r, this._g, this._b); + var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100); + return (this._a == 1) ? + "hsl(" + h + ", " + s + "%, " + l + "%)" : + "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")"; + }, + toHex: function(allow3Char) { + return rgbToHex(this._r, this._g, this._b, allow3Char); + }, + toHexString: function(allow3Char) { + return '#' + this.toHex(allow3Char); + }, + toHex8: function() { + return rgbaToHex(this._r, this._g, this._b, this._a); + }, + toHex8String: function() { + return '#' + this.toHex8(); + }, + toRgb: function() { + return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a }; + }, + toRgbString: function() { + return (this._a == 1) ? + "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" : + "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")"; + }, + toPercentageRgb: function() { + return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a }; + }, + toPercentageRgbString: function() { + return (this._a == 1) ? + "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" : + "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")"; + }, + toName: function() { + if (this._a === 0) { + return "transparent"; + } + + if (this._a < 1) { + return false; + } + + return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false; + }, + toFilter: function(secondColor) { + var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a); + var secondHex8String = hex8String; + var gradientType = this._gradientType ? "GradientType = 1, " : ""; + + if (secondColor) { + var s = tinycolor(secondColor); + secondHex8String = s.toHex8String(); + } + + return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")"; + }, + toString: function(format) { + var formatSet = !!format; + format = format || this._format; + + var formattedString = false; + var hasAlpha = this._a < 1 && this._a >= 0; + var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "name"); + + if (needsAlphaFormat) { + // Special case for "transparent", all other non-alpha formats + // will return rgba when there is transparency. + if (format === "name" && this._a === 0) { + return this.toName(); + } + return this.toRgbString(); + } + if (format === "rgb") { + formattedString = this.toRgbString(); + } + if (format === "prgb") { + formattedString = this.toPercentageRgbString(); + } + if (format === "hex" || format === "hex6") { + formattedString = this.toHexString(); + } + if (format === "hex3") { + formattedString = this.toHexString(true); + } + if (format === "hex8") { + formattedString = this.toHex8String(); + } + if (format === "name") { + formattedString = this.toName(); + } + if (format === "hsl") { + formattedString = this.toHslString(); + } + if (format === "hsv") { + formattedString = this.toHsvString(); + } + + return formattedString || this.toHexString(); + }, + + _applyModification: function(fn, args) { + var color = fn.apply(null, [this].concat([].slice.call(args))); + this._r = color._r; + this._g = color._g; + this._b = color._b; + this.setAlpha(color._a); + return this; + }, + lighten: function() { + return this._applyModification(lighten, arguments); + }, + brighten: function() { + return this._applyModification(brighten, arguments); + }, + darken: function() { + return this._applyModification(darken, arguments); + }, + desaturate: function() { + return this._applyModification(desaturate, arguments); + }, + saturate: function() { + return this._applyModification(saturate, arguments); + }, + greyscale: function() { + return this._applyModification(greyscale, arguments); + }, + spin: function() { + return this._applyModification(spin, arguments); + }, + + _applyCombination: function(fn, args) { + return fn.apply(null, [this].concat([].slice.call(args))); + }, + analogous: function() { + return this._applyCombination(analogous, arguments); + }, + complement: function() { + return this._applyCombination(complement, arguments); + }, + monochromatic: function() { + return this._applyCombination(monochromatic, arguments); + }, + splitcomplement: function() { + return this._applyCombination(splitcomplement, arguments); + }, + triad: function() { + return this._applyCombination(triad, arguments); + }, + tetrad: function() { + return this._applyCombination(tetrad, arguments); + } +}; + +// If input is an object, force 1 into "1.0" to handle ratios properly +// String input requires "1.0" as input, so 1 will be treated as 1 +tinycolor.fromRatio = function(color, opts) { + if (typeof color == "object") { + var newColor = {}; + for (var i in color) { + if (color.hasOwnProperty(i)) { + if (i === "a") { + newColor[i] = color[i]; + } + else { + newColor[i] = convertToPercentage(color[i]); + } + } + } + color = newColor; + } + + return tinycolor(color, opts); +}; + +// Given a string or object, convert that input to RGB +// Possible string inputs: +// +// "red" +// "#f00" or "f00" +// "#ff0000" or "ff0000" +// "#ff000000" or "ff000000" +// "rgb 255 0 0" or "rgb (255, 0, 0)" +// "rgb 1.0 0 0" or "rgb (1, 0, 0)" +// "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" +// "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" +// "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" +// "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" +// "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" +// +function inputToRGB(color) { + + var rgb = { r: 0, g: 0, b: 0 }; + var a = 1; + var ok = false; + var format = false; + + if (typeof color == "string") { + color = stringInputToObject(color); + } + + if (typeof color == "object") { + if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) { + rgb = rgbToRgb(color.r, color.g, color.b); + ok = true; + format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; + } + else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) { + color.s = convertToPercentage(color.s); + color.v = convertToPercentage(color.v); + rgb = hsvToRgb(color.h, color.s, color.v); + ok = true; + format = "hsv"; + } + else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) { + color.s = convertToPercentage(color.s); + color.l = convertToPercentage(color.l); + rgb = hslToRgb(color.h, color.s, color.l); + ok = true; + format = "hsl"; + } + + if (color.hasOwnProperty("a")) { + a = color.a; + } + } + + a = boundAlpha(a); + + return { + ok: ok, + format: color.format || format, + r: mathMin(255, mathMax(rgb.r, 0)), + g: mathMin(255, mathMax(rgb.g, 0)), + b: mathMin(255, mathMax(rgb.b, 0)), + a: a + }; +} + + +// Conversion Functions +// -------------------- + +// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from: +// + +// `rgbToRgb` +// Handle bounds / percentage checking to conform to CSS color spec +// +// *Assumes:* r, g, b in [0, 255] or [0, 1] +// *Returns:* { r, g, b } in [0, 255] +function rgbToRgb(r, g, b){ + return { + r: bound01(r, 255) * 255, + g: bound01(g, 255) * 255, + b: bound01(b, 255) * 255 + }; +} + +// `rgbToHsl` +// Converts an RGB color value to HSL. +// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] +// *Returns:* { h, s, l } in [0,1] +function rgbToHsl(r, g, b) { + + r = bound01(r, 255); + g = bound01(g, 255); + b = bound01(b, 255); + + var max = mathMax(r, g, b), min = mathMin(r, g, b); + var h, s, l = (max + min) / 2; + + if(max == min) { + h = s = 0; // achromatic + } + else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch(max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + + h /= 6; + } + + return { h: h, s: s, l: l }; +} + +// `hslToRgb` +// Converts an HSL color value to RGB. +// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] +// *Returns:* { r, g, b } in the set [0, 255] +function hslToRgb(h, s, l) { + var r, g, b; + + h = bound01(h, 360); + s = bound01(s, 100); + l = bound01(l, 100); + + function hue2rgb(p, q, t) { + if(t < 0) t += 1; + if(t > 1) t -= 1; + if(t < 1/6) return p + (q - p) * 6 * t; + if(t < 1/2) return q; + if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + } + + if(s === 0) { + r = g = b = l; // achromatic + } + else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return { r: r * 255, g: g * 255, b: b * 255 }; +} + +// `rgbToHsv` +// Converts an RGB color value to HSV +// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] +// *Returns:* { h, s, v } in [0,1] +function rgbToHsv(r, g, b) { + + r = bound01(r, 255); + g = bound01(g, 255); + b = bound01(b, 255); + + var max = mathMax(r, g, b), min = mathMin(r, g, b); + var h, s, v = max; + + var d = max - min; + s = max === 0 ? 0 : d / max; + + if(max == min) { + h = 0; // achromatic + } + else { + switch(max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h, s: s, v: v }; +} + +// `hsvToRgb` +// Converts an HSV color value to RGB. +// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] +// *Returns:* { r, g, b } in the set [0, 255] + function hsvToRgb(h, s, v) { + + h = bound01(h, 360) * 6; + s = bound01(s, 100); + v = bound01(v, 100); + + var i = math.floor(h), + f = h - i, + p = v * (1 - s), + q = v * (1 - f * s), + t = v * (1 - (1 - f) * s), + mod = i % 6, + r = [v, q, p, p, t, v][mod], + g = [t, v, v, q, p, p][mod], + b = [p, p, t, v, v, q][mod]; + + return { r: r * 255, g: g * 255, b: b * 255 }; +} + +// `rgbToHex` +// Converts an RGB color to hex +// Assumes r, g, and b are contained in the set [0, 255] +// Returns a 3 or 6 character hex +function rgbToHex(r, g, b, allow3Char) { + + var hex = [ + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)) + ]; + + // Return a 3 character hex if possible + if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) { + return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); + } + + return hex.join(""); +} + // `rgbaToHex` + // Converts an RGBA color plus alpha transparency to hex + // Assumes r, g, b and a are contained in the set [0, 255] + // Returns an 8 character hex + function rgbaToHex(r, g, b, a) { + + var hex = [ + pad2(convertDecimalToHex(a)), + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)) + ]; + + return hex.join(""); + } + +// `equals` +// Can be called with any tinycolor input +tinycolor.equals = function (color1, color2) { + if (!color1 || !color2) { return false; } + return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); +}; +tinycolor.random = function() { + return tinycolor.fromRatio({ + r: mathRandom(), + g: mathRandom(), + b: mathRandom() + }); +}; + + +// Modification Functions +// ---------------------- +// Thanks to less.js for some of the basics here +// + +function desaturate(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.s -= amount / 100; + hsl.s = clamp01(hsl.s); + return tinycolor(hsl); +} + +function saturate(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.s += amount / 100; + hsl.s = clamp01(hsl.s); + return tinycolor(hsl); +} + +function greyscale(color) { + return tinycolor(color).desaturate(100); +} + +function lighten (color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.l += amount / 100; + hsl.l = clamp01(hsl.l); + return tinycolor(hsl); +} + +function brighten(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var rgb = tinycolor(color).toRgb(); + rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100)))); + rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100)))); + rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100)))); + return tinycolor(rgb); +} + +function darken (color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.l -= amount / 100; + hsl.l = clamp01(hsl.l); + return tinycolor(hsl); +} + +// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue. +// Values outside of this range will be wrapped into this range. +function spin(color, amount) { + var hsl = tinycolor(color).toHsl(); + var hue = (mathRound(hsl.h) + amount) % 360; + hsl.h = hue < 0 ? 360 + hue : hue; + return tinycolor(hsl); +} + +// Combination Functions +// --------------------- +// Thanks to jQuery xColor for some of the ideas behind these +// + +function complement(color) { + var hsl = tinycolor(color).toHsl(); + hsl.h = (hsl.h + 180) % 360; + return tinycolor(hsl); +} + +function triad(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }) + ]; +} + +function tetrad(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }) + ]; +} + +function splitcomplement(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}), + tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l}) + ]; +} + +function analogous(color, results, slices) { + results = results || 6; + slices = slices || 30; + + var hsl = tinycolor(color).toHsl(); + var part = 360 / slices; + var ret = [tinycolor(color)]; + + for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) { + hsl.h = (hsl.h + part) % 360; + ret.push(tinycolor(hsl)); + } + return ret; +} + +function monochromatic(color, results) { + results = results || 6; + var hsv = tinycolor(color).toHsv(); + var h = hsv.h, s = hsv.s, v = hsv.v; + var ret = []; + var modification = 1 / results; + + while (results--) { + ret.push(tinycolor({ h: h, s: s, v: v})); + v = (v + modification) % 1; + } + + return ret; +} + +// Utility Functions +// --------------------- + +tinycolor.mix = function(color1, color2, amount) { + amount = (amount === 0) ? 0 : (amount || 50); + + var rgb1 = tinycolor(color1).toRgb(); + var rgb2 = tinycolor(color2).toRgb(); + + var p = amount / 100; + var w = p * 2 - 1; + var a = rgb2.a - rgb1.a; + + var w1; + + if (w * a == -1) { + w1 = w; + } else { + w1 = (w + a) / (1 + w * a); + } + + w1 = (w1 + 1) / 2; + + var w2 = 1 - w1; + + var rgba = { + r: rgb2.r * w1 + rgb1.r * w2, + g: rgb2.g * w1 + rgb1.g * w2, + b: rgb2.b * w1 + rgb1.b * w2, + a: rgb2.a * p + rgb1.a * (1 - p) + }; + + return tinycolor(rgba); +}; + + +// Readability Functions +// --------------------- +// + +// `readability` +// Analyze the 2 colors and returns an object with the following properties: +// `brightness`: difference in brightness between the two colors +// `color`: difference in color/hue between the two colors +tinycolor.readability = function(color1, color2) { + var c1 = tinycolor(color1); + var c2 = tinycolor(color2); + var rgb1 = c1.toRgb(); + var rgb2 = c2.toRgb(); + var brightnessA = c1.getBrightness(); + var brightnessB = c2.getBrightness(); + var colorDiff = ( + Math.max(rgb1.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) + + Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) + + Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b) + ); + + return { + brightness: Math.abs(brightnessA - brightnessB), + color: colorDiff + }; +}; + +// `readable` +// http://www.w3.org/TR/AERT#color-contrast +// Ensure that foreground and background color combinations provide sufficient contrast. +// *Example* +// tinycolor.isReadable("#000", "#111") => false +tinycolor.isReadable = function(color1, color2) { + var readability = tinycolor.readability(color1, color2); + return readability.brightness > 125 && readability.color > 500; +}; + +// `mostReadable` +// Given a base color and a list of possible foreground or background +// colors for that base, returns the most readable color. +// *Example* +// tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000" +tinycolor.mostReadable = function(baseColor, colorList) { + var bestColor = null; + var bestScore = 0; + var bestIsReadable = false; + for (var i=0; i < colorList.length; i++) { + + // We normalize both around the "acceptable" breaking point, + // but rank brightness constrast higher than hue. + + var readability = tinycolor.readability(baseColor, colorList[i]); + var readable = readability.brightness > 125 && readability.color > 500; + var score = 3 * (readability.brightness / 125) + (readability.color / 500); + + if ((readable && ! bestIsReadable) || + (readable && bestIsReadable && score > bestScore) || + ((! readable) && (! bestIsReadable) && score > bestScore)) { + bestIsReadable = readable; + bestScore = score; + bestColor = tinycolor(colorList[i]); + } + } + return bestColor; +}; + + +// Big List of Colors +// ------------------ +// +var names = tinycolor.names = { + aliceblue: "f0f8ff", + antiquewhite: "faebd7", + aqua: "0ff", + aquamarine: "7fffd4", + azure: "f0ffff", + beige: "f5f5dc", + bisque: "ffe4c4", + black: "000", + blanchedalmond: "ffebcd", + blue: "00f", + blueviolet: "8a2be2", + brown: "a52a2a", + burlywood: "deb887", + burntsienna: "ea7e5d", + cadetblue: "5f9ea0", + chartreuse: "7fff00", + chocolate: "d2691e", + coral: "ff7f50", + cornflowerblue: "6495ed", + cornsilk: "fff8dc", + crimson: "dc143c", + cyan: "0ff", + darkblue: "00008b", + darkcyan: "008b8b", + darkgoldenrod: "b8860b", + darkgray: "a9a9a9", + darkgreen: "006400", + darkgrey: "a9a9a9", + darkkhaki: "bdb76b", + darkmagenta: "8b008b", + darkolivegreen: "556b2f", + darkorange: "ff8c00", + darkorchid: "9932cc", + darkred: "8b0000", + darksalmon: "e9967a", + darkseagreen: "8fbc8f", + darkslateblue: "483d8b", + darkslategray: "2f4f4f", + darkslategrey: "2f4f4f", + darkturquoise: "00ced1", + darkviolet: "9400d3", + deeppink: "ff1493", + deepskyblue: "00bfff", + dimgray: "696969", + dimgrey: "696969", + dodgerblue: "1e90ff", + firebrick: "b22222", + floralwhite: "fffaf0", + forestgreen: "228b22", + fuchsia: "f0f", + gainsboro: "dcdcdc", + ghostwhite: "f8f8ff", + gold: "ffd700", + goldenrod: "daa520", + gray: "808080", + green: "008000", + greenyellow: "adff2f", + grey: "808080", + honeydew: "f0fff0", + hotpink: "ff69b4", + indianred: "cd5c5c", + indigo: "4b0082", + ivory: "fffff0", + khaki: "f0e68c", + lavender: "e6e6fa", + lavenderblush: "fff0f5", + lawngreen: "7cfc00", + lemonchiffon: "fffacd", + lightblue: "add8e6", + lightcoral: "f08080", + lightcyan: "e0ffff", + lightgoldenrodyellow: "fafad2", + lightgray: "d3d3d3", + lightgreen: "90ee90", + lightgrey: "d3d3d3", + lightpink: "ffb6c1", + lightsalmon: "ffa07a", + lightseagreen: "20b2aa", + lightskyblue: "87cefa", + lightslategray: "789", + lightslategrey: "789", + lightsteelblue: "b0c4de", + lightyellow: "ffffe0", + lime: "0f0", + limegreen: "32cd32", + linen: "faf0e6", + magenta: "f0f", + maroon: "800000", + mediumaquamarine: "66cdaa", + mediumblue: "0000cd", + mediumorchid: "ba55d3", + mediumpurple: "9370db", + mediumseagreen: "3cb371", + mediumslateblue: "7b68ee", + mediumspringgreen: "00fa9a", + mediumturquoise: "48d1cc", + mediumvioletred: "c71585", + midnightblue: "191970", + mintcream: "f5fffa", + mistyrose: "ffe4e1", + moccasin: "ffe4b5", + navajowhite: "ffdead", + navy: "000080", + oldlace: "fdf5e6", + olive: "808000", + olivedrab: "6b8e23", + orange: "ffa500", + orangered: "ff4500", + orchid: "da70d6", + palegoldenrod: "eee8aa", + palegreen: "98fb98", + paleturquoise: "afeeee", + palevioletred: "db7093", + papayawhip: "ffefd5", + peachpuff: "ffdab9", + peru: "cd853f", + pink: "ffc0cb", + plum: "dda0dd", + powderblue: "b0e0e6", + purple: "800080", + rebeccapurple: "663399", + red: "f00", + rosybrown: "bc8f8f", + royalblue: "4169e1", + saddlebrown: "8b4513", + salmon: "fa8072", + sandybrown: "f4a460", + seagreen: "2e8b57", + seashell: "fff5ee", + sienna: "a0522d", + silver: "c0c0c0", + skyblue: "87ceeb", + slateblue: "6a5acd", + slategray: "708090", + slategrey: "708090", + snow: "fffafa", + springgreen: "00ff7f", + steelblue: "4682b4", + tan: "d2b48c", + teal: "008080", + thistle: "d8bfd8", + tomato: "ff6347", + turquoise: "40e0d0", + violet: "ee82ee", + wheat: "f5deb3", + white: "fff", + whitesmoke: "f5f5f5", + yellow: "ff0", + yellowgreen: "9acd32" +}; + +// Make it easy to access colors via `hexNames[hex]` +var hexNames = tinycolor.hexNames = flip(names); + + +// Utilities +// --------- + +// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` +function flip(o) { + var flipped = { }; + for (var i in o) { + if (o.hasOwnProperty(i)) { + flipped[o[i]] = i; + } + } + return flipped; +} + +// Return a valid alpha value [0,1] with all invalid values being set to 1 +function boundAlpha(a) { + a = parseFloat(a); + + if (isNaN(a) || a < 0 || a > 1) { + a = 1; + } + + return a; +} + +// Take input from [0, n] and return it as [0, 1] +function bound01(n, max) { + if (isOnePointZero(n)) { n = "100%"; } + + var processPercent = isPercentage(n); + n = mathMin(max, mathMax(0, parseFloat(n))); + + // Automatically convert percentage into number + if (processPercent) { + n = parseInt(n * max, 10) / 100; + } + + // Handle floating point rounding errors + if ((math.abs(n - max) < 0.000001)) { + return 1; + } + + // Convert into [0, 1] range if it isn't already + return (n % max) / parseFloat(max); +} + +// Force a number between 0 and 1 +function clamp01(val) { + return mathMin(1, mathMax(0, val)); +} + +// Parse a base-16 hex value into a base-10 integer +function parseIntFromHex(val) { + return parseInt(val, 16); +} + +// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 +// +function isOnePointZero(n) { + return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1; +} + +// Check to see if string passed in is a percentage +function isPercentage(n) { + return typeof n === "string" && n.indexOf('%') != -1; +} + +// Force a hex value to have 2 characters +function pad2(c) { + return c.length == 1 ? '0' + c : '' + c; +} + +// Replace a decimal with it's percentage value +function convertToPercentage(n) { + if (n <= 1) { + n = (n * 100) + "%"; + } + + return n; +} + +// Converts a decimal to a hex value +function convertDecimalToHex(d) { + return Math.round(parseFloat(d) * 255).toString(16); +} +// Converts a hex value to a decimal +function convertHexToDecimal(h) { + return (parseIntFromHex(h) / 255); +} + +var matchers = (function() { + + // + var CSS_INTEGER = "[-\\+]?\\d+%?"; + + // + var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; + + // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. + var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; + + // Actual matching. + // Parentheses and commas are optional, but not required. + // Whitespace can take the place of commas or opening paren + var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; + var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; + + return { + rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), + rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), + hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), + hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), + hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), + hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, + hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ + }; +})(); + +// `stringInputToObject` +// Permissive string parsing. Take in a number of formats, and output an object +// based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` +function stringInputToObject(color) { + + color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase(); + var named = false; + if (names[color]) { + color = names[color]; + named = true; + } + else if (color == 'transparent') { + return { r: 0, g: 0, b: 0, a: 0, format: "name" }; + } + + // Try to match string input using regular expressions. + // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] + // Just return an object and let the conversion functions handle that. + // This way the result will be the same whether the tinycolor is initialized with string or object. + var match; + if ((match = matchers.rgb.exec(color))) { + return { r: match[1], g: match[2], b: match[3] }; + } + if ((match = matchers.rgba.exec(color))) { + return { r: match[1], g: match[2], b: match[3], a: match[4] }; + } + if ((match = matchers.hsl.exec(color))) { + return { h: match[1], s: match[2], l: match[3] }; + } + if ((match = matchers.hsla.exec(color))) { + return { h: match[1], s: match[2], l: match[3], a: match[4] }; + } + if ((match = matchers.hsv.exec(color))) { + return { h: match[1], s: match[2], v: match[3] }; + } + if ((match = matchers.hex8.exec(color))) { + return { + a: convertHexToDecimal(match[1]), + r: parseIntFromHex(match[2]), + g: parseIntFromHex(match[3]), + b: parseIntFromHex(match[4]), + format: named ? "name" : "hex8" + }; + } + if ((match = matchers.hex6.exec(color))) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + format: named ? "name" : "hex" + }; + } + if ((match = matchers.hex3.exec(color))) { + return { + r: parseIntFromHex(match[1] + '' + match[1]), + g: parseIntFromHex(match[2] + '' + match[2]), + b: parseIntFromHex(match[3] + '' + match[3]), + format: named ? "name" : "hex" + }; + } + + return false; +} + +// Node: Export function +if (typeof module !== "undefined" && module.exports) { + module.exports = tinycolor; +} +// AMD/requirejs: Define the module +else if (typeof define === 'function' && define.amd) { + define(function () {return tinycolor;}); +} +// Browser: Expose to window +else { + window.tinycolor = tinycolor; +} + +})(); diff --git a/app/assets/javascripts/trianglify.min.js b/app/assets/javascripts/trianglify.min.js new file mode 100644 index 00000000..ef30d5e3 --- /dev/null +++ b/app/assets/javascripts/trianglify.min.js @@ -0,0 +1 @@ +function Trianglify(f){function e(f,e){return"undefined"!=typeof f?f:e}"undefined"==typeof f&&(f={}),this.options={cellsize:e(f.cellsize,150),bleed:e(f.cellsize,150),cellpadding:e(f.cellpadding,.1*f.cellsize||15),noiseIntensity:e(f.noiseIntensity,0),x_gradient:e(f.x_gradient,Trianglify.randomColor()),format:e(f.format,"svg"),fillOpacity:e(f.fillOpacity,1),strokeOpacity:e(f.strokeOpacity,1)},this.options.y_gradient=f.y_gradient||this.options.x_gradient.map(function(f){return d3.rgb(f).brighter(.5)})}"undefined"!=typeof module&&module.exports&&(d3=require("d3"),jsdom=require("jsdom"),document=new(jsdom.level(1,"core").Document),XMLSerializer=require("xmldom").XMLSerializer,btoa=require("btoa"),module.exports=Trianglify),Trianglify.randomColor=function(){var f=Object.keys(Trianglify.colorbrewer),e=Trianglify.colorbrewer[f[Math.floor(Math.random()*f.length)]];f=Object.keys(e);var d=e[f[Math.floor(Math.random()*f.length)]];return d},Trianglify.prototype.generate=function(f,e){return new Trianglify.Pattern(this.options,f,e)},Trianglify.Pattern=function(f,e,d){this.options=f,this.width=e,this.height=d,this.polys=this.generatePolygons(),this.svg=this.generateSVG();var a=new XMLSerializer;this.svgString=a.serializeToString(this.svg),this.base64=btoa(this.svgString),this.dataUri="data:image/svg+xml;base64,"+this.base64,this.dataUrl="url("+this.dataUri+")"},Trianglify.Pattern.prototype.append=function(){document.body.appendChild(this.svg)},Trianglify.Pattern.gradient_2d=function(f,e,d,a){return function(c,b){var t=d3.scale.linear().range(f).domain(d3.range(0,d,d/f.length)),i=d3.scale.linear().range(e).domain(d3.range(0,a,a/e.length));return d3.interpolateRgb(t(c),i(b))(.5)}},Trianglify.Pattern.prototype.generatePolygons=function(){var f=this.options,e=Math.ceil((this.width+2*f.bleed)/f.cellsize),d=Math.ceil((this.height+2*f.bleed)/f.cellsize),a=d3.range(e*d).map(function(d){var a=d%e,c=Math.floor(d/e),b=Math.round(-f.bleed+a*f.cellsize+Math.random()*(f.cellsize-2*f.cellpadding)+f.cellpadding),t=Math.round(-f.bleed+c*f.cellsize+Math.random()*(f.cellsize-2*f.cellpadding)+f.cellpadding);return[b,t]});return d3.geom.voronoi().triangles(a)},Trianglify.Pattern.prototype.generateSVG=function(){var f=this.options,e=Trianglify.Pattern.gradient_2d(f.x_gradient,f.y_gradient,this.width,this.height),d=document.createElementNS("http://www.w3.org/2000/svg","svg"),a=d3.select(d);a.attr("width",this.width),a.attr("height",this.height),a.attr("xmlns","http://www.w3.org/2000/svg");var c=a.append("g");if(f.noiseIntensity>.01){var b=a.append("filter").attr("id","noise");b.append("feTurbulence").attr("type","fractalNoise").attr("in","fillPaint").attr("fill","#F00").attr("baseFrequency",.7).attr("numOctaves","3").attr("stitchTiles","stitch");var t=b.append("feComponentTransfer");t.append("feFuncR").attr("type","linear").attr("slope","2").attr("intercept","-.5"),t.append("feFuncG").attr("type","linear").attr("slope","2").attr("intercept","-.5"),t.append("feFuncB").attr("type","linear").attr("slope","2").attr("intercept","-.5"),b.append("feColorMatrix").attr("type","matrix").attr("values","0.3333 0.3333 0.3333 0 0 \n 0.3333 0.3333 0.3333 0 0 \n 0.3333 0.3333 0.3333 0 0 \n 0 0 0 1 0"),a.append("rect").attr("opacity",f.noiseIntensity).attr("width","100%").attr("height","100%").attr("filter","url(#noise)")}return this.polys.forEach(function(d){var a=(d[0][0]+d[1][0]+d[2][0])/3,b=(d[0][1]+d[1][1]+d[2][1])/3,t=e(a,b),i=c.append("path").attr("d","M"+d.join("L")+"Z").attr({fill:t,stroke:t});1!=f.fillOpacity&&i.attr("fill-opacity",f.fillOpacity),1!=f.strokeOpacity&&i.attr("stroke-opacity",f.strokeOpacity)}),a.node()},Trianglify.Pattern.prototype.append=function(){document.body.appendChild(this.svg)},Trianglify.colorbrewer={YlGn:{3:["#f7fcb9","#addd8e","#31a354"],4:["#ffffcc","#c2e699","#78c679","#238443"],5:["#ffffcc","#c2e699","#78c679","#31a354","#006837"],6:["#ffffcc","#d9f0a3","#addd8e","#78c679","#31a354","#006837"],7:["#ffffcc","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#005a32"],8:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#005a32"],9:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"]},YlGnBu:{3:["#edf8b1","#7fcdbb","#2c7fb8"],4:["#ffffcc","#a1dab4","#41b6c4","#225ea8"],5:["#ffffcc","#a1dab4","#41b6c4","#2c7fb8","#253494"],6:["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#2c7fb8","#253494"],7:["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"],8:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"],9:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"]},GnBu:{3:["#e0f3db","#a8ddb5","#43a2ca"],4:["#f0f9e8","#bae4bc","#7bccc4","#2b8cbe"],5:["#f0f9e8","#bae4bc","#7bccc4","#43a2ca","#0868ac"],6:["#f0f9e8","#ccebc5","#a8ddb5","#7bccc4","#43a2ca","#0868ac"],7:["#f0f9e8","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#08589e"],8:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#08589e"],9:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"]},BuGn:{3:["#e5f5f9","#99d8c9","#2ca25f"],4:["#edf8fb","#b2e2e2","#66c2a4","#238b45"],5:["#edf8fb","#b2e2e2","#66c2a4","#2ca25f","#006d2c"],6:["#edf8fb","#ccece6","#99d8c9","#66c2a4","#2ca25f","#006d2c"],7:["#edf8fb","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#005824"],8:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#005824"],9:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"]},PuBuGn:{3:["#ece2f0","#a6bddb","#1c9099"],4:["#f6eff7","#bdc9e1","#67a9cf","#02818a"],5:["#f6eff7","#bdc9e1","#67a9cf","#1c9099","#016c59"],6:["#f6eff7","#d0d1e6","#a6bddb","#67a9cf","#1c9099","#016c59"],7:["#f6eff7","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016450"],8:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016450"],9:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"]},PuBu:{3:["#ece7f2","#a6bddb","#2b8cbe"],4:["#f1eef6","#bdc9e1","#74a9cf","#0570b0"],5:["#f1eef6","#bdc9e1","#74a9cf","#2b8cbe","#045a8d"],6:["#f1eef6","#d0d1e6","#a6bddb","#74a9cf","#2b8cbe","#045a8d"],7:["#f1eef6","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#034e7b"],8:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#034e7b"],9:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"]},BuPu:{3:["#e0ecf4","#9ebcda","#8856a7"],4:["#edf8fb","#b3cde3","#8c96c6","#88419d"],5:["#edf8fb","#b3cde3","#8c96c6","#8856a7","#810f7c"],6:["#edf8fb","#bfd3e6","#9ebcda","#8c96c6","#8856a7","#810f7c"],7:["#edf8fb","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#6e016b"],8:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#6e016b"],9:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"]},RdPu:{3:["#fde0dd","#fa9fb5","#c51b8a"],4:["#feebe2","#fbb4b9","#f768a1","#ae017e"],5:["#feebe2","#fbb4b9","#f768a1","#c51b8a","#7a0177"],6:["#feebe2","#fcc5c0","#fa9fb5","#f768a1","#c51b8a","#7a0177"],7:["#feebe2","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177"],8:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177"],9:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"]},PuRd:{3:["#e7e1ef","#c994c7","#dd1c77"],4:["#f1eef6","#d7b5d8","#df65b0","#ce1256"],5:["#f1eef6","#d7b5d8","#df65b0","#dd1c77","#980043"],6:["#f1eef6","#d4b9da","#c994c7","#df65b0","#dd1c77","#980043"],7:["#f1eef6","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#91003f"],8:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#91003f"],9:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"]},OrRd:{3:["#fee8c8","#fdbb84","#e34a33"],4:["#fef0d9","#fdcc8a","#fc8d59","#d7301f"],5:["#fef0d9","#fdcc8a","#fc8d59","#e34a33","#b30000"],6:["#fef0d9","#fdd49e","#fdbb84","#fc8d59","#e34a33","#b30000"],7:["#fef0d9","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#990000"],8:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#990000"],9:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"]},YlOrRd:{3:["#ffeda0","#feb24c","#f03b20"],4:["#ffffb2","#fecc5c","#fd8d3c","#e31a1c"],5:["#ffffb2","#fecc5c","#fd8d3c","#f03b20","#bd0026"],6:["#ffffb2","#fed976","#feb24c","#fd8d3c","#f03b20","#bd0026"],7:["#ffffb2","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#b10026"],8:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#b10026"],9:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"]},YlOrBr:{3:["#fff7bc","#fec44f","#d95f0e"],4:["#ffffd4","#fed98e","#fe9929","#cc4c02"],5:["#ffffd4","#fed98e","#fe9929","#d95f0e","#993404"],6:["#ffffd4","#fee391","#fec44f","#fe9929","#d95f0e","#993404"],7:["#ffffd4","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#8c2d04"],8:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#8c2d04"],9:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"]},Purples:{3:["#efedf5","#bcbddc","#756bb1"],4:["#f2f0f7","#cbc9e2","#9e9ac8","#6a51a3"],5:["#f2f0f7","#cbc9e2","#9e9ac8","#756bb1","#54278f"],6:["#f2f0f7","#dadaeb","#bcbddc","#9e9ac8","#756bb1","#54278f"],7:["#f2f0f7","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#4a1486"],8:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#4a1486"],9:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"]},Blues:{3:["#deebf7","#9ecae1","#3182bd"],4:["#eff3ff","#bdd7e7","#6baed6","#2171b5"],5:["#eff3ff","#bdd7e7","#6baed6","#3182bd","#08519c"],6:["#eff3ff","#c6dbef","#9ecae1","#6baed6","#3182bd","#08519c"],7:["#eff3ff","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#084594"],8:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#084594"],9:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"]},Greens:{3:["#e5f5e0","#a1d99b","#31a354"],4:["#edf8e9","#bae4b3","#74c476","#238b45"],5:["#edf8e9","#bae4b3","#74c476","#31a354","#006d2c"],6:["#edf8e9","#c7e9c0","#a1d99b","#74c476","#31a354","#006d2c"],7:["#edf8e9","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#005a32"],8:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#005a32"],9:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"]},Oranges:{3:["#fee6ce","#fdae6b","#e6550d"],4:["#feedde","#fdbe85","#fd8d3c","#d94701"],5:["#feedde","#fdbe85","#fd8d3c","#e6550d","#a63603"],6:["#feedde","#fdd0a2","#fdae6b","#fd8d3c","#e6550d","#a63603"],7:["#feedde","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#8c2d04"],8:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#8c2d04"],9:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"]},Reds:{3:["#fee0d2","#fc9272","#de2d26"],4:["#fee5d9","#fcae91","#fb6a4a","#cb181d"],5:["#fee5d9","#fcae91","#fb6a4a","#de2d26","#a50f15"],6:["#fee5d9","#fcbba1","#fc9272","#fb6a4a","#de2d26","#a50f15"],7:["#fee5d9","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#99000d"],8:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#99000d"],9:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"]},Greys:{3:["#f0f0f0","#bdbdbd","#636363"],4:["#f7f7f7","#cccccc","#969696","#525252"],5:["#f7f7f7","#cccccc","#969696","#636363","#252525"],6:["#f7f7f7","#d9d9d9","#bdbdbd","#969696","#636363","#252525"],7:["#f7f7f7","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525"],8:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525"],9:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"]},PuOr:{3:["#f1a340","#f7f7f7","#998ec3"],4:["#e66101","#fdb863","#b2abd2","#5e3c99"],5:["#e66101","#fdb863","#f7f7f7","#b2abd2","#5e3c99"],6:["#b35806","#f1a340","#fee0b6","#d8daeb","#998ec3","#542788"],7:["#b35806","#f1a340","#fee0b6","#f7f7f7","#d8daeb","#998ec3","#542788"],8:["#b35806","#e08214","#fdb863","#fee0b6","#d8daeb","#b2abd2","#8073ac","#542788"],9:["#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788"],10:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"],11:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"]},BrBG:{3:["#d8b365","#f5f5f5","#5ab4ac"],4:["#a6611a","#dfc27d","#80cdc1","#018571"],5:["#a6611a","#dfc27d","#f5f5f5","#80cdc1","#018571"],6:["#8c510a","#d8b365","#f6e8c3","#c7eae5","#5ab4ac","#01665e"],7:["#8c510a","#d8b365","#f6e8c3","#f5f5f5","#c7eae5","#5ab4ac","#01665e"],8:["#8c510a","#bf812d","#dfc27d","#f6e8c3","#c7eae5","#80cdc1","#35978f","#01665e"],9:["#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e"],10:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"],11:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"]},PRGn:{3:["#af8dc3","#f7f7f7","#7fbf7b"],4:["#7b3294","#c2a5cf","#a6dba0","#008837"],5:["#7b3294","#c2a5cf","#f7f7f7","#a6dba0","#008837"],6:["#762a83","#af8dc3","#e7d4e8","#d9f0d3","#7fbf7b","#1b7837"],7:["#762a83","#af8dc3","#e7d4e8","#f7f7f7","#d9f0d3","#7fbf7b","#1b7837"],8:["#762a83","#9970ab","#c2a5cf","#e7d4e8","#d9f0d3","#a6dba0","#5aae61","#1b7837"],9:["#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837"],10:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"],11:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"]},PiYG:{3:["#e9a3c9","#f7f7f7","#a1d76a"],4:["#d01c8b","#f1b6da","#b8e186","#4dac26"],5:["#d01c8b","#f1b6da","#f7f7f7","#b8e186","#4dac26"],6:["#c51b7d","#e9a3c9","#fde0ef","#e6f5d0","#a1d76a","#4d9221"],7:["#c51b7d","#e9a3c9","#fde0ef","#f7f7f7","#e6f5d0","#a1d76a","#4d9221"],8:["#c51b7d","#de77ae","#f1b6da","#fde0ef","#e6f5d0","#b8e186","#7fbc41","#4d9221"],9:["#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221"],10:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"],11:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"]},RdBu:{3:["#ef8a62","#f7f7f7","#67a9cf"],4:["#ca0020","#f4a582","#92c5de","#0571b0"],5:["#ca0020","#f4a582","#f7f7f7","#92c5de","#0571b0"],6:["#b2182b","#ef8a62","#fddbc7","#d1e5f0","#67a9cf","#2166ac"],7:["#b2182b","#ef8a62","#fddbc7","#f7f7f7","#d1e5f0","#67a9cf","#2166ac"],8:["#b2182b","#d6604d","#f4a582","#fddbc7","#d1e5f0","#92c5de","#4393c3","#2166ac"],9:["#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac"],10:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"],11:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"]},RdGy:{3:["#ef8a62","#ffffff","#999999"],4:["#ca0020","#f4a582","#bababa","#404040"],5:["#ca0020","#f4a582","#ffffff","#bababa","#404040"],6:["#b2182b","#ef8a62","#fddbc7","#e0e0e0","#999999","#4d4d4d"],7:["#b2182b","#ef8a62","#fddbc7","#ffffff","#e0e0e0","#999999","#4d4d4d"],8:["#b2182b","#d6604d","#f4a582","#fddbc7","#e0e0e0","#bababa","#878787","#4d4d4d"],9:["#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d"],10:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"],11:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"]},RdYlBu:{3:["#fc8d59","#ffffbf","#91bfdb"],4:["#d7191c","#fdae61","#abd9e9","#2c7bb6"],5:["#d7191c","#fdae61","#ffffbf","#abd9e9","#2c7bb6"],6:["#d73027","#fc8d59","#fee090","#e0f3f8","#91bfdb","#4575b4"],7:["#d73027","#fc8d59","#fee090","#ffffbf","#e0f3f8","#91bfdb","#4575b4"],8:["#d73027","#f46d43","#fdae61","#fee090","#e0f3f8","#abd9e9","#74add1","#4575b4"],9:["#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4"],10:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"],11:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"]},Spectral:{3:["#fc8d59","#ffffbf","#99d594"],4:["#d7191c","#fdae61","#abdda4","#2b83ba"],5:["#d7191c","#fdae61","#ffffbf","#abdda4","#2b83ba"],6:["#d53e4f","#fc8d59","#fee08b","#e6f598","#99d594","#3288bd"],7:["#d53e4f","#fc8d59","#fee08b","#ffffbf","#e6f598","#99d594","#3288bd"],8:["#d53e4f","#f46d43","#fdae61","#fee08b","#e6f598","#abdda4","#66c2a5","#3288bd"],9:["#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd"],10:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"],11:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"]},RdYlGn:{3:["#fc8d59","#ffffbf","#91cf60"],4:["#d7191c","#fdae61","#a6d96a","#1a9641"],5:["#d7191c","#fdae61","#ffffbf","#a6d96a","#1a9641"],6:["#d73027","#fc8d59","#fee08b","#d9ef8b","#91cf60","#1a9850"],7:["#d73027","#fc8d59","#fee08b","#ffffbf","#d9ef8b","#91cf60","#1a9850"],8:["#d73027","#f46d43","#fdae61","#fee08b","#d9ef8b","#a6d96a","#66bd63","#1a9850"],9:["#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850"],10:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"],11:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"]}}; \ No newline at end of file diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 25a8d80e..a9d2d93b 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -12,4 +12,5 @@ *= require font-awesome *= require bootstrap-markdown.min *= require bootstrap-datetimepicker + *= require leaflet */ diff --git a/app/assets/stylesheets/breakpoints.css.scss b/app/assets/stylesheets/breakpoints.css.scss index 46986e2e..b2025e39 100644 --- a/app/assets/stylesheets/breakpoints.css.scss +++ b/app/assets/stylesheets/breakpoints.css.scss @@ -8,11 +8,11 @@ } @else if $class == md { - @media (min-width: 970px) { @content; } + @media (min-width: 992px) { @content; } } @else if $class == lg { - @media (min-width: 1170px) { @content; } + @media (min-width: 1200px) { @content; } } @else { diff --git a/app/assets/stylesheets/osem-splash.css.scss b/app/assets/stylesheets/osem-splash.css.scss index b2737fb2..717c9ab4 100644 --- a/app/assets/stylesheets/osem-splash.css.scss +++ b/app/assets/stylesheets/osem-splash.css.scss @@ -1,4 +1,8 @@ +@import "breakpoints.css.scss"; + #splash { + // Counter the general padding for #content + margin-bottom: -60px; section { padding-top: 60px; padding-bottom: 60px; @@ -11,114 +15,158 @@ section:nth-child(odd) { background: none repeat scroll 0 0 #ffffff; color: #7b7b7b; + .thumbnail { + background: none repeat scroll 0 0 #e0e0e0; + } } -} -#splash-banner{ - background: none; - background-repeat: no-repeat; - background-position: center center; - width: 100%; - background-size: cover; - min-height: 700px; - margin-top: -10px; - .container { + .cta-button { + padding-top: 30px; + } + + #banner{ + background-repeat: no-repeat; + background-position: center center; + background-size: cover; + margin-top: -10px; + padding-top: 100px; + padding-bottom: 100px; + .container { + #header { + background-color: rgba(224, 224, 224,.80); + padding-top: 20px; + padding-bottom: 20px; + } + } + } + + #program { + h3 { + padding-left: 5px; + } + .track { + padding: 20px; + } + .track:hover{ + background-color: #F0FFFF; + } + } + + #callforpapers { + .timer-box{ + width: 130px; + margin: 35px 24px 20px 0; + border-radius: 50%; + border:4px solid #989797; + } + } + + #venue { + padding-top: 0px; + padding-bottom: 0px; + } + + #lodging { + @include breakpoint(xs) { + .img-lodging{ + max-width: 280px; + } + } + @include breakpoint(sm) { + .img-lodging{ + max-width: 200px; + } + } + @include breakpoint(sm) { + .img-lodging{ + max-width: 260px; + } + } + @include breakpoint(lg) { + .img-lodging{ + max-width: 300px; + max-height: 200px; + } + } + } + + #sponsors { + .img-sponsor { + max-height: 100px; + } + .img-sponsor-1 { + max-height: 200px; + } + .img-sponsor-2 { + max-height: 150px; + } + .img-sponsor-3 { + max-height: 120px; + } + @include breakpoint(xs) { + .img-sponsor, .img-sponsor-1, .img-sponsor-3, .img-sponsor-3{ + max-height: unset; + max-width: 280px; + } + } + } + + #social-media{ + background: none repeat scroll 0 0 #2f2f2f; padding-top: 60px; + padding-bottom: 60px; + i{ + color: #4a4a4a; + } + i:hover{ + color: #16a085; + } + a{ + padding-left: 100px; + } + a:nth-child(-n+1) { + padding-left: 0px; + } + @include breakpoint(xs) { + a{ + padding-left: 10px; + } + } } - h1, h3{ - color:#3399CC; - } - h3{ - font-family: 'Coustard', serif; - font-weight: 600; - text-shadow: 0.2em 0.2em 0 #4A4F6A; - } - h1{ - font-size: 5em; - font-weight: 700; - text-shadow:0.04em 0.04em 0 black; - } - p { - color: #fff; - font-weight: 500; - } -} - -#program { - .tracks:hover{ - background-color: white; - } -} - -#callforpapers { - .timer-box{ - width: 130px; - margin: 35px 24px 20px 0; - border-radius: 50%; - border:4px solid #989797; - } - #cfp-date{ - font-size: 40px; - color: #ff6633; - } -} - -#location { - background-repeat: no-repeat; - background-position: center center; - width: 100%; - background-size: cover; - min-height: 500px; - h1,h2,p{ - color: #fff; - } - h1,h2,li,p{ - text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.6); - font-weight: 400; - } -} - -#social-media{ - i{ - color: #4a4a4a; - } - i:hover{ - color: #16a085; - } -} - -.scroll-top-wrapper { - position: fixed; - opacity: 0; - visibility: hidden; - overflow: hidden; - text-align: center; - z-index: 99999999; - background-color: #424242; - width: 50px; - height: 48px; - line-height: 48px; - right: 30px; - bottom: 30px; - padding-top: 2px; - border-top-left-radius: 10px; - border-top-right-radius: 10px; - border-bottom-right-radius: 10px; - border-bottom-left-radius: 10px; - -webkit-transition: all 0.5s ease-in-out; - -moz-transition: all 0.5s ease-in-out; - -ms-transition: all 0.5s ease-in-out; - -o-transition: all 0.5s ease-in-out; - transition: all 0.5s ease-in-out; - i.fa { - line-height: inherit; - } - &.show { - visibility:visible; - cursor:pointer; - opacity: 1.0; - } - a { - color: white; + + .scroll-top-wrapper { + position: fixed; + opacity: 0; + visibility: hidden; + overflow: hidden; + text-align: center; + z-index: 99999999; + background-color: #424242; + width: 50px; + height: 48px; + line-height: 48px; + right: 30px; + bottom: 30px; + padding-top: 2px; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + border-bottom-right-radius: 10px; + border-bottom-left-radius: 10px; + -webkit-transition: all 0.5s ease-in-out; + -moz-transition: all 0.5s ease-in-out; + -ms-transition: all 0.5s ease-in-out; + -o-transition: all 0.5s ease-in-out; + transition: all 0.5s ease-in-out; + i.fa { + line-height: inherit; + } + &.show { + visibility:visible; + cursor:pointer; + opacity: 1.0; + } + a { + color: white; + } } } \ No newline at end of file diff --git a/app/assets/stylesheets/osem.css.scss b/app/assets/stylesheets/osem.css.scss index 18195a9c..624e968d 100644 --- a/app/assets/stylesheets/osem.css.scss +++ b/app/assets/stylesheets/osem.css.scss @@ -5,11 +5,15 @@ html { body { /* Margin bottom by 2 times the footer height */ - margin-bottom: 120px; + margin-bottom: 60px; /* Margin bottom by navbar height */ padding-top: 60px; } +#content { + padding-bottom: 60px; +} + #footer { position: absolute; bottom: 0; @@ -24,4 +28,25 @@ body { .nav-tabs { margin-bottom: 15px; +} + +.img-center { + margin: 0 auto; +} + +/* centered columns styles */ +.row-centered { + text-align:center; +} +.col-centered { + display:inline-block; + float:none; + /* reset the text-align */ + text-align:left; + /* inline-block space fix */ + margin-right:-4px; +} + +.col-top { + vertical-align:top; } \ No newline at end of file diff --git a/app/assets/stylesheets/strap-on.css.scss b/app/assets/stylesheets/strap-on.css.scss index a54d2984..7d73b0b4 100644 --- a/app/assets/stylesheets/strap-on.css.scss +++ b/app/assets/stylesheets/strap-on.css.scss @@ -59,4 +59,4 @@ $navbar-default-link-hover-color: #000000; // Utility classes @import "bootstrap/utilities"; -@import "bootstrap/responsive-utilities"; +@import "bootstrap/responsive-utilities"; \ No newline at end of file diff --git a/app/controllers/admin/lodgings_controller.rb b/app/controllers/admin/lodgings_controller.rb index e05ea3b0..43600b26 100644 --- a/app/controllers/admin/lodgings_controller.rb +++ b/app/controllers/admin/lodgings_controller.rb @@ -1,23 +1,21 @@ module Admin class LodgingsController < Admin::BaseController load_and_authorize_resource :conference, find_by: :short_title - load_and_authorize_resource :venue, through: :conference, singleton: true - load_and_authorize_resource :lodging, through: :venue + load_and_authorize_resource :lodging, through: :conference def index - authorize! :update, Lodging.new(venue_id: @venue.id) end def show; end def new - @lodging = @venue.lodgings.new + @lodging = @conference.lodgings.new end def create - @lodging = @venue.lodgings.new(lodging_params) + @lodging = @conference.lodgings.new(lodging_params) if @lodging.save - redirect_to(admin_conference_lodging_path(conference_id: @conference.short_title, id: @lodging.id), + redirect_to(admin_conference_lodgings_path(conference_id: @conference.short_title), notice: 'Lodging successfully created.') else flash[:error] = "Creating Lodging failed: #{@lodging.errors.full_messages.join('. ')}." diff --git a/app/controllers/admin/venues_controller.rb b/app/controllers/admin/venues_controller.rb index 1a11713a..9bb8e9b0 100644 --- a/app/controllers/admin/venues_controller.rb +++ b/app/controllers/admin/venues_controller.rb @@ -3,16 +3,48 @@ module Admin load_and_authorize_resource :conference, find_by: :short_title load_and_authorize_resource :venue, through: :conference, singleton: true + def show; end + + def new + @venue = @conference.build_venue + end + def edit; end + def create + @venue = @conference.build_venue(venue_params) + + if @venue.save + redirect_to admin_conference_venue_path, + notice: 'Venue successfully created.' + else + render :new + end + end + def update - if @venue.update_attributes(params[:venue]) - redirect_to(edit_admin_conference_venue_path(conference_id: @conference.short_title), + if @venue.update_attributes(venue_params) + redirect_to(admin_conference_venue_path(conference_id: @conference.short_title), notice: 'Venue was successfully updated.') else flash[:error] = "Update venue failed: #{@venue.errors.full_messages.join('. ')}." render :edit end end + + def destroy + if @venue.destroy + redirect_to admin_conference_venue_path, notice: 'Venue was successfully deleted.' + else + redirect_to admin_conference_venue_path, alert: 'A error prohibited this Venue from being destroyed: '\ + "#{@venue.errors.full_messages.join('. ')}." + end + end + + private + + def venue_params + params[:venue] + end end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e84b9a57..9da23c54 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -171,6 +171,34 @@ module ApplicationHelper result end + def event_types(conference) + all = conference.event_types.map { |et | et.title.pluralize } + first = all[0...-1] + last = all[-1] + ets = '' + if all.length > 1 + ets << first.join(', ') + ets << " and #{last}" + else + ets = all.join + end + return ets + end + + def tracks(conference) + all = conference.tracks.map {|t| t.name} + first = all[0...-1] + last = all[-1] + ts = '' + if all.length > 1 + ts << first.join(', ') + ts << " and #{last}" + else + ts = all.join + end + return ts + end + def markdown(text) options = { autolink: true, diff --git a/app/models/ability.rb b/app/models/ability.rb index ba6f1093..9ec2b3ee 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -43,21 +43,15 @@ class Ability def user_with_roles(user) conf_ids_for_organizer = [] - venue_ids_for_organizer = [] conf_ids_for_cfp = [] - venue_ids_for_cfp = [] conf_ids_for_info_desk = [] conf_ids_for_volunteer_coordinator = [] # Ids of all the conferences for which the user has an 'organizer' role conf_ids_for_organizer = Conference.with_role(:organizer, user).pluck(:id) if user.has_role? :organizer, :any - venue_ids_for_organizer = - Conference.with_role(:organizer, user).pluck(:venue_id) if user.has_role? :organizer, :any conf_ids_for_cfp = Conference.with_role(:cfp, user).pluck(:id) if user.has_role? :cfp, :any - venue_ids_for_cfp = - Conference.with_role(:cfp, user).pluck(:venue_id) if user.has_role? :cfp, :any # Ids of all the conferences for which the user has an 'info_desk' role conf_ids_for_info_desk = Conference.with_role(:info_desk, user).pluck(:id) if user.has_role? :info_desk, :any @@ -74,8 +68,6 @@ class Ability # can :manage, Conference do |conference| # conference.id = conf_ids_for_organizer # end - can :manage, Venue, id: venue_ids_for_organizer - can :index, Venue, id: venue_ids_for_cfp can :manage, Registration, conference_id: conf_ids_for_organizer + conf_ids_for_info_desk can :manage, Question, conference_id: conf_ids_for_organizer + conf_ids_for_info_desk cannot [:edit, :update, :destroy], Question, global: true @@ -92,7 +84,9 @@ class Ability can :manage, DifficultyLevel, conference_id: conf_ids_for_organizer + conf_ids_for_cfp can :manage, EmailSettings, conference_id: conf_ids_for_organizer + conf_ids_for_cfp can :manage, Campaign, conference_id: conf_ids_for_organizer - can :manage, Lodging, venue_id: venue_ids_for_organizer + can :manage, Venue, conference_id: conf_ids_for_organizer + can :index, Venue, conference_id: conf_ids_for_organizer + conf_ids_for_cfp + can :manage, Lodging, conference_id: conf_ids_for_organizer can :manage, Photo, conference_id: conf_ids_for_organizer can :manage, Room, conference_id: conf_ids_for_organizer + conf_ids_for_cfp can :manage, Sponsor, conference_id: conf_ids_for_organizer diff --git a/app/models/conference.rb b/app/models/conference.rb index f71c05f3..63c4065d 100644 --- a/app/models/conference.rb +++ b/app/models/conference.rb @@ -8,7 +8,7 @@ class Conference < ActiveRecord::Base default_scope { order('start_date DESC') } - attr_accessible :title, :short_title, :timezone, :html_export_path, + attr_accessible :title, :short_title, :description, :timezone, :html_export_path, :start_date, :end_date, :rooms_attributes, :tracks_attributes, :dietary_choices_attributes, :use_dietary_choices, :tickets_attributes, :social_events_attributes, :event_types_attributes, @@ -29,6 +29,7 @@ class Conference < ActiveRecord::Base has_one :registration_period, dependent: :destroy has_one :email_settings, dependent: :destroy has_one :call_for_papers, dependent: :destroy + has_one :venue, dependent: :destroy has_many :social_events, dependent: :destroy has_many :ticket_purchases has_many :supporters, through: :ticket_purchases, source: :user @@ -53,6 +54,7 @@ class Conference < ActiveRecord::Base has_many :tracks, dependent: :destroy has_many :difficulty_levels, dependent: :destroy has_many :rooms, dependent: :destroy + has_many :lodgings, dependent: :destroy has_many :registrations, dependent: :destroy has_many :participants, through: :registrations, source: :user has_many :vdays, dependent: :destroy @@ -64,7 +66,6 @@ class Conference < ActiveRecord::Base has_many :campaigns, dependent: :destroy has_many :commercials, as: :commercialable, dependent: :destroy has_many :subscriptions, dependent: :destroy - belongs_to :venue accepts_nested_attributes_for :rooms, reject_if: proc { |r| r['name'].blank? }, allow_destroy: true accepts_nested_attributes_for :tracks, reject_if: proc { |r| r['name'].blank? }, allow_destroy: true @@ -99,7 +100,6 @@ class Conference < ActiveRecord::Base validates_uniqueness_of :short_title validates_format_of :short_title, with: /\A[a-zA-Z0-9_-]*\z/ before_create :generate_guid - before_create :create_venue before_create :create_event_types before_create :create_email_settings before_create :add_color @@ -727,14 +727,13 @@ class Conference < ActiveRecord::Base rooms.count > 0 end - ## - # Checks if venue has a name, address and website. + # Checks if the conference has a venue object. # # ====Returns - # * +True+ -> If venue has a name, address and website. - # * +False+ -> venue has a no name, address or website. + # * +True+ -> If conference has a venue object. + # * +False+ -> IF conference has no venue object. def venue_set? - !!venue && !!venue.name && !!venue.address && !!venue.website + !!venue end ## @@ -885,14 +884,6 @@ class Conference < ActiveRecord::Base result end - ## - # Creates a Venue for this Conference. Used as before_create. - # - def create_venue - self.venue_id = Venue.create.id - true - end - ## # Creates default EventTypes for this Conference. Used as before_create. # diff --git a/app/models/contact.rb b/app/models/contact.rb index 829088b7..3eecfb43 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -10,4 +10,9 @@ class Contact < ActiveRecord::Base validates :facebook, :twitter, :googleplus, :instagram, format: URI::regexp(%w(http https)), allow_blank: true + + def has_social_media? + return true if !facebook.blank? || !twitter.blank? || !googleplus.blank? || !instagram.blank? + false + end end diff --git a/app/models/lodging.rb b/app/models/lodging.rb index 554c6e8a..7c37a047 100644 --- a/app/models/lodging.rb +++ b/app/models/lodging.rb @@ -1,6 +1,6 @@ class Lodging < ActiveRecord::Base - attr_accessible :name, :description, :photo, :website_link, :venue_id - belongs_to :venue + attr_accessible :name, :description, :photo, :website_link, :conference_id + belongs_to :conference validates :name, presence: true diff --git a/app/models/splashpage.rb b/app/models/splashpage.rb index da698015..e414f75b 100644 --- a/app/models/splashpage.rb +++ b/app/models/splashpage.rb @@ -1,15 +1,8 @@ class Splashpage < ActiveRecord::Base belongs_to :conference - - attr_accessible :banner_description, :ticket_description, :sponsor_description, :lodging_description, - :registration_description, :include_registrations, :include_sponsors, - :include_tracks, :include_tickets, :include_program, :public, :banner_photo, :include_banner, - :include_social_media, :include_lodgings, :include_venue, :lodging_description - - has_attached_file :banner_photo, - styles: { thumb: '100x100>', large: '1300x700>' } - - validates_attachment_content_type :banner_photo, - content_type: [/jpg/, /jpeg/, /png/, /gif/], - size: { in: 0..500.kilobytes } + attr_accessible :public, + :include_tracks, :include_program, + :include_venue, :include_registrations, + :include_tickets, :include_lodgings, + :include_sponsors, :include_social_media end diff --git a/app/models/venue.rb b/app/models/venue.rb index 3f9dffbd..2eab0d82 100644 --- a/app/models/venue.rb +++ b/app/models/venue.rb @@ -1,30 +1,39 @@ class Venue < ActiveRecord::Base - attr_accessible :name, :description, :website, :address, :photo, :lodgings_attributes, - :include_venue_in_splash, :include_lodgings_in_splash - has_many :conferences + belongs_to :conference has_many :lodgings before_create :generate_guid + + attr_accessible :name, :street, :postalcode, :city, :country, :longitude, :latitude, :description, :website, :photo, :lodgings_attributes, :conference_id + validates :name, :street, :city, :country, presence: true + has_attached_file :photo, styles: { thumb: '100x100>', large: '300x300>' } - validates_attachment_content_type :photo, content_type: [/jpg/, /jpeg/, /png/, /gif/], size: { in: 0..500.kilobytes } + accepts_nested_attributes_for :lodgings, allow_destroy: true after_update :send_mail_notification + def address + "#{conference.venue.street}, #{conference.venue.postalcode} #{conference.venue.city}, #{conference.venue.country}" + end + + def country_name + name = ISO3166::Country[country] + name.name if name + end + private def send_mail_notification - conferences.each do |conference| - Mailbot.delay.send_email_on_venue_update(conference) if venue_notify?(conference) - end + Mailbot.delay.send_email_on_venue_update(conference) if venue_notify?(conference) end def venue_notify?(conference) - (self.name_changed? || self.address_changed?) && - (!self.name.blank? && !self.address.blank?) && + (self.name_changed? || self.street_changed?) && + (!self.name.blank? && !self.street.blank?) && (conference.email_settings.send_on_venue_update && !conference.email_settings.venue_update_subject.blank? && conference.email_settings.venue_update_template) diff --git a/app/views/admin/conference/_edit_form.html.haml b/app/views/admin/conference/_edit_form.html.haml index c4708b00..117c52c2 100644 --- a/app/views/admin/conference/_edit_form.html.haml +++ b/app/views/admin/conference/_edit_form.html.haml @@ -1,8 +1,9 @@ .row .col-md-8 = semantic_form_for(@conference, :url => admin_conference_path(@conference.short_title),:html => {:multipart => true}) do |f| - = f.input :title, :hint => "The full name of the conference, such as 'openSUSE Conference 2013'" - = f.input :short_title, :hint => "A short title, such as 'osc2013', to be used in URLs" + = f.input :title, :hint => "The full title of the conference, e.g. 'openSUSE Conference 2014'" + = f.input :short_title, :hint => "A short title, e.g. 'oSC14', to be used in URLs" + = f.input :description, hint: markdown_hint('A description of the conference.'), input_html: { rows: 5, data: { provide: 'markdown-editable' } } = f.input :color, :hint => "The color will be used eg for the dashboard.", :input_html => {:size => 6, :type => "color"} - if !@conference.logo.blank? = image_tag @conference.logo(:thumb) diff --git a/app/views/admin/conference/_edit_show.html.haml b/app/views/admin/conference/_edit_show.html.haml index 22446f6e..aed09aad 100644 --- a/app/views/admin/conference/_edit_show.html.haml +++ b/app/views/admin/conference/_edit_show.html.haml @@ -9,6 +9,11 @@ Short Title %dd = @conference.short_title + %dt + Description + %dd + - unless @conference.description.blank? + = markdown(@conference.description) %dt Date %dd diff --git a/app/views/admin/lodgings/_form.html.haml b/app/views/admin/lodgings/_form.html.haml index 0e397359..9c4d7765 100644 --- a/app/views/admin/lodgings/_form.html.haml +++ b/app/views/admin/lodgings/_form.html.haml @@ -1,8 +1,8 @@ -= f.input :name -= f.input :description, :input_html => {:rows => 2, data: { provide: "markdown-editable" } }, hint: markdown_hint("Write about the hotel/place, of what they are offering, about types of rooms, prices and address.") -= image_tag f.object.photo(:thumb) if !f.object.photo.blank? -= f.input :photo -= f.input :website_link -= f.action :submit, as: :button, button_html: { class: 'btn btn-primary' } - -= link_to 'Back', admin_conference_lodgings_path(@conference.short_title) += semantic_form_for(@lodging, :url => (@lodging.new_record? ? admin_conference_lodgings_path : admin_conference_lodging_path(@conference.short_title, @lodging))) do |f| + = f.input :name + = f.input :website_link + = f.input :description, input_html: { rows: 5, cols: 20, data: { provide: 'markdown-editable' } }, hint: markdown_hint + - unless @lodging.photo.blank? + = image_tag @lodging.photo(:thumb) + = f.input :photo + = f.action :submit, as: :button, button_html: { class: 'btn btn-primary' } diff --git a/app/views/admin/lodgings/edit.html.haml b/app/views/admin/lodgings/edit.html.haml deleted file mode 100644 index 8e9b1d22..00000000 --- a/app/views/admin/lodgings/edit.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -%h1 - Edit Lodging -.row - .col-md-8 - = semantic_form_for(@lodging, :url => admin_conference_lodging_path(@conference.short_title, @lodging)) do |f| - = render partial: 'form', locals: { f: f } diff --git a/app/views/admin/lodgings/index.html.haml b/app/views/admin/lodgings/index.html.haml index 68ebf00b..f3a15e45 100644 --- a/app/views/admin/lodgings/index.html.haml +++ b/app/views/admin/lodgings/index.html.haml @@ -1,5 +1,5 @@ %h1 Lodgings -- if @venue.lodgings.any? +- if @conference.lodgings.any? .row .col-md-12 %table.table @@ -9,7 +9,7 @@ %th Edit %th Delete %tbody - - @venue.lodgings.each_with_index do |lodging, index| + - @conference.lodgings.each_with_index do |lodging, index| %tr %td = index + 1 diff --git a/app/views/admin/lodgings/new.html.haml b/app/views/admin/lodgings/new.html.haml deleted file mode 100644 index 1e5ea564..00000000 --- a/app/views/admin/lodgings/new.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -%h1 - New Lodging -.row - .col-md-8 - = semantic_form_for(@lodging, :url => admin_conference_lodgings_path(@conference.short_title, @lodging)) do |f| - = render partial: 'form', locals: { f: f } diff --git a/app/views/admin/splashpages/_form.html.haml b/app/views/admin/splashpages/_form.html.haml index 5585a5f9..bbafa330 100644 --- a/app/views/admin/splashpages/_form.html.haml +++ b/app/views/admin/splashpages/_form.html.haml @@ -2,26 +2,14 @@ .row .col-md-8 = semantic_form_for(@splashpage, url: admin_conference_splashpage_path(@conference.short_title)) do |f| - = f.inputs name: 'Banner' do - = f.input :banner_photo, hint: 'This will be the top most component of the splash. This background cover will contain start_date and end_date of the conference and the description.' - = f.input :banner_description, hint: markdown_hint('This description will be shown at the bottom of the banner photo of the Splashpage.'), input_html: { rows: 5, data: { provide: 'markdown-editable' } } - = f.input :include_banner, label: 'Display banner on the splashpage?' = f.inputs name: 'Components' do - = f.input :ticket_description, hint: markdown_hint('This will appear in the Tickets segment of the splash.'), input_html: { rows: 5, data: { provide: 'markdown-editable' } } - = f.input :include_tickets, label: 'Display tickets on the splashpage?' - %br - = f.input :sponsor_description, hint: markdown_hint('This will appear in the Sponsors segment of the splash.'), input_html: { rows: 5, data: { provide: 'markdown-editable' } } - = f.input :include_sponsors, label: 'Display sponsors on the splashpage?' - %br - = f.input :registration_description, hint: markdown_hint(''), input_html: { rows: 5, data: { provide: 'markdown-editable' } } - = f.input :include_registrations, label: 'Display the registration period on the splashpage?' - %br - = f.input :lodging_description, hint: markdown_hint('This will appear in the Lodgings segment of the splash.'), input_html: { rows: 5, data: { provide: 'markdown-editable' } } - = f.input :include_lodgings, label: 'Display the lodgings on the splashpage?' - %br = f.input :include_tracks, label: 'Display tracks on the splashpage?' = f.input :include_program, label: 'Display program on the splashpage?' - = f.input :include_social_media, label: 'Display social media on the splashpage?' = f.input :include_venue, label: 'Display venue on the splashpage?' - = f.input :public, label: 'Make splash page public! (Attention: Please do this only after you have finished the configuration of the conference!)' + = f.input :include_registrations, label: 'Display the registration period on the splashpage?' + = f.input :include_tickets, label: 'Display tickets on the splashpage?' + = f.input :include_lodgings, label: 'Display the lodgings on the splashpage?' + = f.input :include_sponsors, label: 'Display sponsors on the splashpage?' + = f.input :include_social_media, label: 'Display social media on the splashpage?' + = f.input :public, label: 'Make splash page public?' = f.submit 'Save Splashpage', class: 'btn btn-primary' diff --git a/app/views/admin/splashpages/show.html.haml b/app/views/admin/splashpages/show.html.haml index 2c7addc0..f10db054 100644 --- a/app/views/admin/splashpages/show.html.haml +++ b/app/views/admin/splashpages/show.html.haml @@ -4,11 +4,6 @@ .row .col-md-8 %dl.dl-horizontal - %dt - Ticket: - %dd - - unless @splashpage.ticket_description.blank? - = markdown(@splashpage.ticket_description) %dt Include Tickets: %dd @@ -16,11 +11,6 @@ Yes - else No - %dt - Sponsor: - %dd - - unless @splashpage.sponsor_description.blank? - = markdown(@splashpage.sponsor_description) %dt Include Sponsors: %dd @@ -28,11 +18,6 @@ Yes - else No - %dt - Registration: - %dd - - unless @splashpage.registration_description.blank? - = markdown(@splashpage.registration_description) %dt Include Registrations: %dd @@ -40,11 +25,6 @@ Yes - else No - %dt - Lodging: - %dd - - unless @splashpage.lodging_description.blank? - = markdown(@splashpage.lodging_description) %dt Include Tracks: %dd @@ -74,34 +54,6 @@ - else No - .row.row-flex.row-flex-wrap - .col-md-4 - .thumbnail.flex-col - %h3.text-center - Conference Banner - - if @splashpage.banner_photo? - = image_tag(@splashpage.banner_photo(:large), class: 'img-responsive') - .caption.flex-grow - .caption - %p - %dl.dl-horizontal - %dt - Filename - %dd - = @splashpage.banner_photo_file_name - %dt Description - %dd - - unless @splashpage.banner_description.blank? - = markdown(@splashpage.banner_description) - %dt Included - %dd - - if @splashpage.include_banner - Yes - - else - No - - else - %h4.text-center - Not set! %br - if can? :update, @splashpage = link_to 'Edit', edit_admin_conference_splashpage_path, class: 'btn btn-primary' diff --git a/app/views/admin/venues/_form.html.haml b/app/views/admin/venues/_form.html.haml index f94ddd7f..bc74818c 100644 --- a/app/views/admin/venues/_form.html.haml +++ b/app/views/admin/venues/_form.html.haml @@ -1,8 +1,7 @@ = semantic_form_for(@venue, url: admin_conference_venue_path(@conference.short_title)) do |f| - = f.input :name, input_html: { rows: 1 } - = f.input :address, input_html: { rows: 1 } - = f.input :website + = f.inputs :name, :website = f.input :description, input_html: { rows: 5, cols: 20, data: { provide: 'markdown-editable' } }, hint: markdown_hint + = f.inputs :street, :postalcode, :city, :country, :longitude, :latitude - unless @venue.photo.blank? = image_tag @venue.photo(:thumb) = f.input :photo diff --git a/app/views/admin/venues/_show.html.haml b/app/views/admin/venues/_show.html.haml deleted file mode 100644 index fa6688c6..00000000 --- a/app/views/admin/venues/_show.html.haml +++ /dev/null @@ -1,38 +0,0 @@ -.row{'style'=>'padding-top: 15px;'} - .col-md-6 - %dl.dl-horizontal - %dt - Name - %dd - = @venue.name - %dt - Address - %dd - = @venue.address - %dt - Website - %dd - = @venue.website - %dt - Description - %dd - - unless @venue.description.blank? - = markdown(@venue.description) -.row.row-flex.row-flex-wrap - .col-md-4 - .thumbnail.flex-col - %h3.text-center - Venue Logo - - if @venue.photo - = image_tag(@venue.photo(:large), class: 'img-responsive') - .caption.flex-grow - .caption - %p - %dl.dl-horizontal - %dt - Filename - %dd - = @venue.photo_file_name - -else - %h4.text-center - Not set! \ No newline at end of file diff --git a/app/views/admin/venues/edit.html.haml b/app/views/admin/venues/edit.html.haml deleted file mode 100644 index d5c798a7..00000000 --- a/app/views/admin/venues/edit.html.haml +++ /dev/null @@ -1,16 +0,0 @@ -.row - .col-md-12 - %ul.nav.nav-tabs{'role'=>'tablist'} - %li.active - %a{'href'=> '#show', 'role'=>'tab', 'data-toggle'=>'tab'} - Show - %li - %a{'href'=> '#edit', 'role'=>'tab', 'data-toggle'=>'tab'} - Edit -.row - .col-md-8 - .tab-content - .tab-pane.active#show - = render partial: 'show' - .tab-pane#edit - = render partial: 'form' diff --git a/app/views/admin/venues/show.html.haml b/app/views/admin/venues/show.html.haml new file mode 100644 index 00000000..f421aeaa --- /dev/null +++ b/app/views/admin/venues/show.html.haml @@ -0,0 +1,25 @@ +-if @venue + .row + .col-md-6 + =image_tag(@conference.venue.photo, class: 'img-responsive img-rounded') unless @conference.venue.photo.blank? + .col-md-6 + %address + %strong + = @venue.name + %br + = @venue.street + %br + = "#{@venue.postalcode}, #{@venue.city}" + %br + = @venue.country_name + .row + .col-md-12 + = link_to(edit_admin_conference_venue_path(@conference.short_title), class: 'btn btn-primary') do + Edit Venue + = link_to(admin_conference_venue_path(@conference.short_title), method: 'delete', class: 'btn btn-danger') do + Delete Venue +-else + .row + .col-md-12 + = link_to(new_admin_conference_venue_path(@conference.short_title), class: 'btn btn-success') do + Create Venue \ No newline at end of file diff --git a/app/views/conference/_call_for_papers.html.haml b/app/views/conference/_call_for_papers.html.haml index 51e58a87..e3f618af 100644 --- a/app/views/conference/_call_for_papers.html.haml +++ b/app/views/conference/_call_for_papers.html.haml @@ -5,55 +5,35 @@ .container .row .col-md-12.text-center - %h1 - Call For Papers - - if !@conference.call_for_papers.description.blank? - = markdown(@conference.call_for_papers.description) + %h2 + Call for Papers + %p.lead + We are ready to accept your proposals for sessions! + .row + .col-md-6.col-md-offset-3.col-sm-10.col-sm-offset-1 + %p + - if @conference.event_types.any? + You can submit proposals for + = "#{event_types(@conference)}." + - if @conference.tracks.any? + Proposals should fit in one of the + = "#{pluralize(@conference.tracks.count, 'track')}:" + = "#{tracks(@conference)}." + The submission period has begun + %em + = @conference.call_for_papers.start_date.strftime('%A, %B %-d. %Y') + and closes + %em + = @conference.call_for_papers.end_date.strftime('%A, %B %-d. %Y.') + That means you have only + - days = (@conference.call_for_papers.end_date - Date.today).to_i + %b + = pluralize(days, 'days') + left! + Remember + = @conference.short_title + will only be as good as the sessions you present. Submit early, submit often! .row .col-md-12.text-center - .lead - = link_to "Submit Your Proposals Today", conference_proposal_index_path(@conference.short_title), class: 'btn btn-info', target: '_blank' - - if !@conference.call_for_papers.start_date.blank? && !@conference.call_for_papers.end_date.blank? - %p - Proposals will be accepted between - %p#cfp-date - = date_string(@conference.call_for_papers.start_date, @conference.call_for_papers.end_date) - .row - .col-md-8.col-md-offset-3.text-center - %div.col-md-2.timer-box - %h2#days - .lead Days - %div.col-md-2.timer-box - %h2#hours - .lead Hours - %div.col-md-2.timer-box - %h2#minutes - .lead Minutes - %div.col-md-2.timer-box - %h2#seconds - .lead Seconds - -:javascript - $( document ).ready(function(){ - var target_date = new Date("#{@conference.call_for_papers.end_date}").getTime(); - if(target_date > new Date().getTime()) - var days, hours, minutes, seconds; - setInterval(function () { - var current_date = new Date().getTime(); - var seconds_left = (target_date - current_date) / 1000; - days = parseInt(seconds_left / 86400); - seconds_left = seconds_left % 86400; - - hours = parseInt(seconds_left / 3600); - seconds_left = seconds_left % 3600; - - minutes = parseInt(seconds_left / 60); - seconds = parseInt(seconds_left % 60); - - $('#days').text(days); - $('#hours').text(hours); - $('#minutes').text(minutes); - $('#seconds').text(seconds); - }, 1000); - }); - + %p.cta-button + = link_to "Submit your paper now", conference_proposal_index_path(@conference.short_title), class: 'btn btn-success btn-lg text-center' \ No newline at end of file diff --git a/app/views/conference/_conference_details.html.haml b/app/views/conference/_conference_details.html.haml index 9dd90e4e..29d12933 100644 --- a/app/views/conference/_conference_details.html.haml +++ b/app/views/conference/_conference_details.html.haml @@ -10,14 +10,6 @@ %small %b = date_string(conference.start_date, conference.end_date) - - if conference.venue.name and conference.venue.website and conference.venue.address - %p - %small< - = link_to conference.venue.name, conference.venue.website - ,  - \#{link_to conference.venue.address, "http://maps.google.com/maps?q=#{conference.venue.address}"} - - if conference.venue.description - = simple_format(conference.venue.description, class: 'lead') .col-md-2 .btn-group-vertical - if current_user.nil? || !current_user.subscribed?(conference) diff --git a/app/views/conference/_footer.html.haml b/app/views/conference/_footer.html.haml index 571d56ea..e27eb76e 100644 --- a/app/views/conference/_footer.html.haml +++ b/app/views/conference/_footer.html.haml @@ -1,5 +1,5 @@ %div.scroll-top-wrapper - = link_to "#splash-banner", class: "smoothscroll" do + = link_to "#banner", class: "smoothscroll" do %i.fa.fa-2x.fa-arrow-circle-up :javascript diff --git a/app/views/conference/_location.html.haml b/app/views/conference/_location.html.haml deleted file mode 100644 index 2cff45e3..00000000 --- a/app/views/conference/_location.html.haml +++ /dev/null @@ -1,20 +0,0 @@ -= content_for :splash_nav do - %li - %a.smoothscroll{ href: '#location' } Location - -.container - .row - .col-md-12.text-center - - unless @conference.venue.name.blank? - %h1 - %strong #{ @conference.venue.name } - - unless @conference.venue.address.blank? - = link_to("http://maps.google.com/maps?q=#{@conference.venue.address}") do - %h2 - #{ @conference.venue.address } - - unless @conference.venue.description.blank? - .lead - = markdown(@conference.venue.description) - - unless @conference.venue.website.blank? - %p.lead - = link_to(@conference.venue.website, @conference.venue.website) diff --git a/app/views/conference/_lodging.html.haml b/app/views/conference/_lodging.html.haml index 1a13065e..3ce4c2f6 100644 --- a/app/views/conference/_lodging.html.haml +++ b/app/views/conference/_lodging.html.haml @@ -4,16 +4,23 @@ %h2 Accommodation Deals %p.lead We have prepared affordable accommodation deals for your visit. - .row - - @conference.venue.lodgings.each do |r| - %div{ class: (@conference.venue.lodgings.count.to_i <= 2 ? "col-md-#{12/@conference.venue.lodgings.count.to_i}" : "col-md-4") } - .div.thumbnail - -unless r.photo.blank? - = image_tag r.photo(:large), class: 'img-responsive' - -unless r.name.blank? - %h4.text-center #{ r.name } - -unless r.description.blank? - .lead.text-left #{ markdown(r.description) } - - unless r.website_link.blank? - .text-center - = link_to 'Go to Website', r.website_link + - @conference.lodgings.each_slice(3) do |slice| + .row.row-centered + - slice.each do |lodging| + .col-md-4.col-sm-4.ticket.col-centered.col-top + .thumbnail + - if lodging.photo.blank? + %p.text-center + %i.fa.fa-home.fa-5x + - else + -if lodging.website_link.present? + = link_to(lodging.website_link, class: 'thumbnail') do + = image_tag lodging.photo(:large), class: 'img-responsive img-lodging' + - else + = image_tag lodging.photo(:large), class: 'img-responsive img-lodging' + .caption + %h3.text-center + = lodging.name + -if lodging.description.present? + = markdown(lodging.description) + diff --git a/app/views/conference/_program.html.haml b/app/views/conference/_program.html.haml index 84aa5f97..a07de85a 100644 --- a/app/views/conference/_program.html.haml +++ b/app/views/conference/_program.html.haml @@ -1,36 +1,34 @@ -= content_for :splash_nav do - %li - =link_to('#program', class: 'smoothscroll') do - Program - .container .row - .col-md-12.text-center - %h1 Program - - if @conference.splashpage and @conference.splashpage.include_tracks - .row - .col-md-12 - - @conference.tracks.each do |t| - .tracks{ class: (@conference.tracks.count.to_i <= 2 ? "col-md-#{12/@conference.tracks.count.to_i}" : "col-md-4") } - %h4.text-center - = t.name - %p - = markdown(t.description) - - if @conference.call_for_papers and @conference.call_for_papers.schedule_public - .row - .col-md-12 - %p.text-center - Check out our - = link_to 'Schedule', conference_schedule_path(@conference.short_title) - - if !@keynote_speakers.blank? - %div.row.text-center - %div.col-md-12 - %h3 Keynote Speakers - - @keynote_speakers.each do |k| - %div{ class: (@keynote_speakers.count.to_i <= 2 ? "col-md-#{12/@keynote_speakers.count.to_i}" : "col-md-4") } - = image_tag(k.gravatar_url(size: '80'), class: 'img-circle') unless k.gravatar_url.blank? - %h4 - = k.name - -unless k.biography.blank? - %p - = k.biography + .col-md-12 + %h2.text-center + Program + %p.lead.text-center + = @conference.short_title + has the most awesome program ever! + - if @conference.splashpage and @conference.tracks.any? and @conference.splashpage.include_tracks + See rock-star speakers cover the topics of + - if @conference.splashpage and @conference.splashpage.include_tracks + - @conference.tracks.each_slice(3) do |slice| + .row.row-centered + - slice.each do |track| + .col-md-4.col-sm-4.col-centered.col-top.track + %h4.text-center + = track.name + = markdown(track.description) + + - if @conference.call_for_papers and @conference.call_for_papers.schedule_public + .row + .col-md-12 + %p.cta-button.text-center + = link_to(conference_schedule_path(@conference.short_title), class: 'btn btn-default btn-lg') do + Full Schedule + + - #FIXME: Display keynotes https://github.com/openSUSE/osem/issues/544 + - #FIXME: Display schedule highlights https://github.com/openSUSE/osem/issues/545 + + + = content_for :splash_nav do + %li + =link_to('#program', class: 'smoothscroll') do + Program \ No newline at end of file diff --git a/app/views/conference/_registration.html.haml b/app/views/conference/_registration.html.haml index 5a5480cf..a19ba66b 100644 --- a/app/views/conference/_registration.html.haml +++ b/app/views/conference/_registration.html.haml @@ -9,8 +9,11 @@ %p.lead Going to = @conference.short_title - is free of charge. We only ask you to - = link_to "register yourself", new_conference_conference_registrations_path(@conference.short_title) - until - = @conference.registration_period.end_date - + is free of charge. + %p + We only ask you to register yourself until + = @conference.registration_period.end_date.strftime('%A, %B %-d. %Y') + so we can plan for the right amount of people. + %p.cta-button + = link_to(new_conference_conference_registrations_path(@conference.short_title), class: 'btn btn-lg btn-success') do + Register Now diff --git a/app/views/conference/_social_media.html.haml b/app/views/conference/_social_media.html.haml index 7aca46bd..eefcbd0c 100644 --- a/app/views/conference/_social_media.html.haml +++ b/app/views/conference/_social_media.html.haml @@ -2,21 +2,18 @@ %li %a.smoothscroll{ href: '#social-media' } Social Media -%div.container#social-media.text-center - %div.row - - unless @conference.contact.facebook.blank? - %div.col-md-3 +.container + .row + .col-md-12.text-center + - unless @conference.contact.facebook.blank? = link_to "#{ @conference.contact.facebook }" do %i.fa.fa-facebook-square.fa-4x - - unless @conference.contact.twitter.blank? - %div.col-md-3 + - unless @conference.contact.twitter.blank? = link_to "#{ @conference.contact.twitter }" do %i.fa.fa-twitter.fa-4x - - unless @conference.contact.instagram.blank? - %div.col-md-3 + - unless @conference.contact.instagram.blank? = link_to "#{ @conference.contact.instagram }" do %i.fa.fa-instagram.fa-4x - - unless @conference.contact.googleplus.blank? - %div.col-md-3 + - unless @conference.contact.googleplus.blank? = link_to "#{ @conference.contact.googleplus }" do %i.fa.fa-google-plus-square.fa-4x diff --git a/app/views/conference/_sponsors.html.haml b/app/views/conference/_sponsors.html.haml index bb1755e3..16100358 100644 --- a/app/views/conference/_sponsors.html.haml +++ b/app/views/conference/_sponsors.html.haml @@ -12,16 +12,21 @@ wouldn't be possible! - @conference.sponsorship_levels.each do |sponsorship_level| -if sponsorship_level.sponsors.any? - .row - .col-md-12.text-center - %h3 - = sponsorship_level.title - sponsorship_level.sponsors.each_slice(3) do |slice| - .row + .row.row-centered - slice.each do |sponsor| - .col-md-4 - = link_to("http://#{sponsor.website_url}", class: 'thumbnail') do - = image_tag(sponsor.logo(:large), alt: "#{sponsor.name} Logo", title: "#{sponsor.description}") + .col-md-4.col-sm-4.col-centered.col-top + .thumbnail + - if sponsor.logo.blank? + %h3.text-center + = link_to(sponsor.website_url, title: "#{sponsor.name}") do + = sponsor.name + - else + = link_to(sponsor.website_url, class: 'thumbnail') do + = image_tag sponsor.logo, class: "img-responsive img-sponsor img-sponsor-#{sponsorship_level.position}", title: "#{sponsor.name}" + .caption + -if sponsor.description.present? + = markdown(sponsor.description) -if @conference.contact and !@conference.contact.sponsor_email.blank? .row .col-md-12 diff --git a/app/views/conference/_tickets.html.haml b/app/views/conference/_tickets.html.haml index 5f8e43ec..41108b78 100644 --- a/app/views/conference/_tickets.html.haml +++ b/app/views/conference/_tickets.html.haml @@ -1,21 +1,25 @@ .container .row .col-md-12.text-center - %h1 + %h2 Support =@conference.short_title %p.lead - To support our event you can purchase tickets - .row - - @conference.tickets.each do |ticket| - %div{ class: (@conference.tickets.count <= 2 ? "col-md-#{12/@conference.tickets.count}" : "col-md-4") } - - if ticket.title.present? - %h4.text-center - =ticket.title - - if ticket.description.present? - = markdown(ticket.description) - .text-center - .btn-group - = link_to(conference_tickets_path(@conference.short_title), class: 'btn btn-success') do - Buy Ticket - = "#{humanized_money_with_symbol ticket.price}" + To support our event you can purchase these tickets + - @conference.tickets.each_slice(4) do |slice| + .row.row-centered + - slice.each do |ticket| + .col-md-3.col-centered.col-top.col-sm-3 + .thumbnail + %p.text-center + %i.fa.fa-ticket.fa-5x + .caption + %h3.text-center + = ticket.title + -if ticket.description.present? + = markdown(ticket.description) + %p.text-center + = link_to(conference_tickets_path(@conference.short_title), class: 'btn btn-success') do + Buy Ticket + = humanized_money_with_symbol ticket.price + diff --git a/app/views/conference/_venue.html.haml b/app/views/conference/_venue.html.haml new file mode 100644 index 00000000..5c8742bb --- /dev/null +++ b/app/views/conference/_venue.html.haml @@ -0,0 +1,43 @@ += content_for :splash_nav do + %li + %a.smoothscroll{ href: '#venue' } Venue +-if !@conference.venue.latitude.blank? and !@conference.venue.longitude.blank? + #map{style: "height: 500px;" } + - popup = "

#{@conference.venue.name}


#{@conference.venue.street}
#{@conference.venue.postalcode}, #{@conference.venue.city}
#{@conference.venue.country_name}" + - content_for(:script_body) do + :javascript + // create a map in the "map" div, set the view to a given place and zoom + var map = L.map('map', {scrollWheelZoom: false}).setView([#{@conference.venue.longitude}, #{@conference.venue.latitude}], 11); + // add an OpenStreetMap tile layer + L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { + attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox', + maxZoom: 18 + }).addTo(map); + // add a marker in the given location, attach some popup content to it and open the popup + L.marker([#{@conference.venue.longitude}, #{@conference.venue.latitude}]).addTo(map) + .bindPopup("#{popup}") + .openPopup(); +-else + .container + .row + .col-md-12 + %h2.text-center + = "#{@conference.venue.city} / #{@conference.venue.country_name}" + .col-md-6 + .thumbnail + =image_tag(@conference.venue.photo, class: 'img-responsive img-rounded') unless @conference.venue.photo.blank? + .caption + - unless @conference.venue.description.blank? + = markdown(@conference.venue.description) + .col-md-6 + %address + %h1 + = @conference.venue.name + = @conference.venue.street + %br + = "#{@conference.venue.postalcode}, #{@conference.venue.city}" + %br + = @conference.venue.country_name + - if @conference.venue.website + %br + =link_to @conference.venue.website, @conference.venue.website diff --git a/app/views/conference/show.html.haml b/app/views/conference/show.html.haml index a5b6e8f4..35cfce79 100644 --- a/app/views/conference/show.html.haml +++ b/app/views/conference/show.html.haml @@ -1,51 +1,73 @@ #splash - if @conference.splashpage - - if @conference.splashpage.include_banner? - #splash-banner{ style: ("background-image: url(#{@conference.splashpage.banner_photo})" unless @conference.splashpage.banner_photo.blank?) } + #banner + .container + .row + .col-md-8.col-md-offset-2#header + .row + .col-md-4 + = image_tag(@conference.logo(:original), class: 'img-responsive img-center', id: 'splash-logo') if @conference.logo? + .col-md-8 + %h1 + = @conference.title + %p.lead + - if @conference.venue + = "#{@conference.venue.city} / #{@conference.venue.country_name}" + - if @conference.start_date && @conference.end_date + %br + = date_string(@conference.start_date, @conference.end_date) + + - unless @conference.description.blank? + %section#about .container .row - .col-md-12.text-center - %h1= @conference.title - - if @conference.start_date && @conference.end_date - %h3= date_string(@conference.start_date, @conference.end_date) - - unless @conference.splashpage.banner_description.blank? - %p.lead - = markdown(@conference.splashpage.banner_description) - -unless @conference.photos.blank? - = link_to 'Gallery', gallery_photos_conference_path(@conference.short_title), class: 'btn btn-primary btn-lg', id: 'gallery-btn', remote: true - = render 'gallery' - - - if @conference.splashpage.include_program - %section#program - = render 'program' - - - if @conference.cfp_open? and @conference.call_for_papers.include_cfp_in_splash? - %section#callforpapers - = render 'call_for_papers' - - - if @conference.venue and @conference.splashpage.include_venue - #location{ style: ("background-image: url(#{@conference.venue.photo})" unless @conference.venue.photo.blank?) } - = render 'location' - + .col-md-8.col-md-offset-2 + %h3.text-center + = markdown(@conference.description) + - if @conference.registration_open? and @conference.splashpage.include_registrations %section#registration = render 'registration' - + + - if @conference.splashpage.include_program + %section#program + = render 'program' + + - if @conference.cfp_open? and @conference.call_for_papers.include_cfp_in_splash? + %section#callforpapers + = render 'call_for_papers' + + - if @conference.venue and @conference.splashpage.include_venue + %section#venue + = render 'venue' + + - if @conference.lodgings.any? and @conference.splashpage.include_lodgings + %section#lodging + = render 'lodging' + - if @conference.tickets.any? and @conference.splashpage.include_tickets %section#tickets = render 'tickets' - - - if @conference.venue.lodgings.any? and @conference.splashpage.include_lodgings - %section#lodging - = render 'lodging' - + - if @conference.sponsors.any? and @conference.splashpage.include_sponsors %section#sponsors = render 'sponsors' - - - if @conference.splashpage.include_social_media + + - if @conference.splashpage.include_social_media and @conference.contact.has_social_media? %section#social-media = render 'social_media' - + // grmbl = render 'footer' + +- content_for :script_head do + :javascript + var triangle_tcs = tinycolor("#{@conference.color}").monochromatic(); + var triangle_colors = triangle_tcs.map(function(t) { return t.toHexString(); }); + $(function () { + $(document).ready(function() { + var t = new Trianglify({cellsize: 100, x_gradient: triangle_colors }); + var pattern = t.generate(document.body.clientWidth, ($( "#banner" ).height() + 200 )); + $('#banner').css('background-image', pattern.dataUrl); + }); + }); \ No newline at end of file diff --git a/app/views/conference_registrations/show.html.haml b/app/views/conference_registrations/show.html.haml index 84537b39..4a876fd8 100644 --- a/app/views/conference_registrations/show.html.haml +++ b/app/views/conference_registrations/show.html.haml @@ -8,7 +8,7 @@ = date_string(@conference.start_date, @conference.end_date) .row .col-md-6 - - if @conference.venue.name and @conference.venue.website and @conference.venue.address + - if @conference.venue.name and @conference.venue.website and @conference.venue.street %p %small at diff --git a/app/views/layouts/_admin_sidebar.html.haml b/app/views/layouts/_admin_sidebar.html.haml index c30127ad..1271319e 100644 --- a/app/views/layouts/_admin_sidebar.html.haml +++ b/app/views/layouts/_admin_sidebar.html.haml @@ -43,18 +43,18 @@ %li{:class=> "#{active_nav_li(admin_conference_photos_path(@conference.short_title))}"} = link_to 'Photos', admin_conference_photos_path(@conference.short_title) - if can? :update, @conference - %li{:class=> active_nav_li(admin_conference_splashpage_path(@conference.short_title))} - = link_to 'Splashpage', admin_conference_splashpage_path(@conference.short_title) - - if can? :index, @conference.venue - %li{:class=> "#{active_nav_li(edit_admin_conference_venue_path(@conference.short_title))}"} - = link_to(edit_admin_conference_venue_path(@conference.short_title)) do + %li{:class=> active_nav_li(edit_admin_conference_splashpage_path(@conference.short_title))} + = link_to 'Splashpage', edit_admin_conference_splashpage_path(@conference.short_title) + - if can? :index, Venue.new(conference_id: @conference.id) + %li{:class=> "#{active_nav_li(admin_conference_venue_path(@conference.short_title))}"} + = link_to(admin_conference_venue_path(@conference.short_title)) do %span.fa.fa-road Venue %ul - if can? :update, @conference.rooms.build %li{:class=> active_nav_li(admin_conference_rooms_path(@conference.short_title))} = link_to 'Rooms', admin_conference_rooms_path(@conference.short_title) - - if can? :update, @conference.venue.lodgings.build + - if can? :update, @conference.lodgings.build %li{ class: active_nav_li(admin_conference_lodgings_path(@conference.short_title)) } = link_to 'Lodgings', admin_conference_lodgings_path(@conference.short_title) %li diff --git a/app/views/layouts/_messages.html.haml b/app/views/layouts/_messages.html.haml index c1792cd3..406087d7 100644 --- a/app/views/layouts/_messages.html.haml +++ b/app/views/layouts/_messages.html.haml @@ -8,11 +8,10 @@ %p OSEM requires JavaScript to be enabled to function. Please turn on JavaScript in your browser's settings and reload the page to continue. - flash.each do |type, message| - .container - .row - .col-md-12 - %div{:class=>"alert alert-dismissable #{bootstrap_class_for(type)}", :id=>"flash"} - .button.close{"data-dismiss" => "alert", "aria-hidden"=>"true"} - × - %p - = message \ No newline at end of file + .row + .col-md-12 + %div{:class=>"alert alert-dismissable #{bootstrap_class_for(type)}", :id=>"flash"} + .button.close{"data-dismiss" => "alert", "aria-hidden"=>"true"} + × + %p + = message \ No newline at end of file diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 9915ab6a..b2d652ee 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -15,14 +15,9 @@ detectlang: true, autocollect: true }; - - $(function() { - $('.dropdown input, .dropdown label').click(function(e) { - e.stopPropagation(); - }); - }); - + = content_for(:script_head) = javascript_include_tag "//cdn.transifex.com/live.js" + = yield(:head) %body = render 'layouts/navigation' @@ -31,7 +26,8 @@ = render 'layouts/admin' -else #messages - = render 'layouts/messages' + .container + = render 'layouts/messages' #content = yield #footer @@ -45,4 +41,5 @@ You can run, copy, distribute, study, change and improve it. The source code and the developers are on =link_to "github.", "https://github.com/openSUSE/osem" + = content_for(:script_body) = piwik_tracking_tag diff --git a/config/routes.rb b/config/routes.rb index 7caa0366..2de9a3fd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -40,7 +40,7 @@ Osem::Application.routes.draw do resource :splashpage - resource :venue, only: [:edit, :update] + resource :venue resources :difficulty_levels, only: [:show, :update, :index] diff --git a/db/migrate/20141117214230_move_banner_description_to_conference.rb b/db/migrate/20141117214230_move_banner_description_to_conference.rb new file mode 100644 index 00000000..c90c5a8f --- /dev/null +++ b/db/migrate/20141117214230_move_banner_description_to_conference.rb @@ -0,0 +1,25 @@ +class MoveBannerDescriptionToConference < ActiveRecord::Migration + class TempConference < ActiveRecord::Base + self.table_name = 'conferences' + attr_accessible :description + end + + class TempSplashpage < ActiveRecord::Base + self.table_name = 'splashpages' + end + + def change + add_column :conferences, :description, :text + + TempConference.reset_column_information + # Copy value from splash to conferenc + TempConference.all.each do |conference| + if TempSplashpage.exists?(conference_id: conference.id) + splash = TempSplashpage.find_by(conference_id: conference.id) + conference.update_attributes(description: splash.banner_description) + end + end + + remove_column :splashpages, :banner_description, :text + end +end diff --git a/db/migrate/20141117222919_drop_splash_descriptions_and_photo.rb b/db/migrate/20141117222919_drop_splash_descriptions_and_photo.rb new file mode 100644 index 00000000..343ea467 --- /dev/null +++ b/db/migrate/20141117222919_drop_splash_descriptions_and_photo.rb @@ -0,0 +1,10 @@ +class DropSplashDescriptionsAndPhoto < ActiveRecord::Migration + def change + remove_column :splashpages, :ticket_description + remove_column :splashpages, :sponsor_description + remove_column :splashpages, :registration_description + remove_column :splashpages, :lodging_description + remove_column :splashpages, :include_banner + remove_attachment :splashpages, :banner_photo + end +end diff --git a/db/migrate/20141118143700_add_address_fields_to_venue.rb b/db/migrate/20141118143700_add_address_fields_to_venue.rb new file mode 100644 index 00000000..01df5d9b --- /dev/null +++ b/db/migrate/20141118143700_add_address_fields_to_venue.rb @@ -0,0 +1,12 @@ +class AddAddressFieldsToVenue < ActiveRecord::Migration + def change + add_column :venues, :street, :string + add_column :venues, :postalcode, :integer + add_column :venues, :city, :string + add_column :venues, :country, :string + add_column :venues, :latitude, :string + add_column :venues, :longitude, :string + + remove_column :venues, :address, :text + end +end diff --git a/db/migrate/20141118150427_cleanup_venue.rb b/db/migrate/20141118150427_cleanup_venue.rb new file mode 100644 index 00000000..b985c676 --- /dev/null +++ b/db/migrate/20141118150427_cleanup_venue.rb @@ -0,0 +1,7 @@ +class CleanupVenue < ActiveRecord::Migration + def change + change_column :venues, :name, :string + remove_column :venues, :offline_map_url, :string + remove_column :venues, :offline_map_bounds, :string + end +end diff --git a/db/migrate/20141118153918_change_venue_conference_association.rb b/db/migrate/20141118153918_change_venue_conference_association.rb new file mode 100644 index 00000000..25f0d0f5 --- /dev/null +++ b/db/migrate/20141118153918_change_venue_conference_association.rb @@ -0,0 +1,25 @@ +class ChangeVenueConferenceAssociation < ActiveRecord::Migration + class TempConference < ActiveRecord::Base + self.table_name = 'conferences' + end + + class TempVenue < ActiveRecord::Base + self.table_name = 'venues' + attr_accessible :conference_id + end + + def change + add_column :venues, :conference_id, :integer + TempVenue.reset_column_information + + # Change association from venue and conference + TempConference.all.each do |conference| + if TempVenue.exists?(id: conference.venue_id) + venue = TempVenue.find_by(id: conference.venue_id) + venue.update_attributes(conference_id: conference.id) + end + end + + remove_column :conferences, :venue_id, :integer + end +end diff --git a/db/migrate/20141118162030_change_lodging_association_to_conference.rb b/db/migrate/20141118162030_change_lodging_association_to_conference.rb new file mode 100644 index 00000000..974754dc --- /dev/null +++ b/db/migrate/20141118162030_change_lodging_association_to_conference.rb @@ -0,0 +1,32 @@ +class ChangeLodgingAssociationToConference < ActiveRecord::Migration + class TempConference < ActiveRecord::Base + self.table_name = 'conferences' + end + + class TempVenue < ActiveRecord::Base + self.table_name = 'venues' + end + + class TempLodging < ActiveRecord::Base + self.table_name = 'lodgings' + attr_accessible :conference_id + end + + def change + add_column :lodgings, :conference_id, :integer + TempLodging.reset_column_information + + # Change association from venue and conference + TempConference.all.each do |conference| + if TempVenue.exists?(conference_id: conference.id) + venue = TempVenue.find_by(conference_id: conference.id) + lodgings = TempLodging.where(venue_id: venue.id) + lodgings.each do |lodging| + lodging.update_attributes(conference_id: conference.id) + end + end + end + + remove_column :lodgings, :venue_id, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index f1d20fc4..0f876f1f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20141113134103) do +ActiveRecord::Schema.define(version: 20141118162030) do create_table "ahoy_events", force: true do |t| t.uuid "visit_id" @@ -27,21 +27,21 @@ ActiveRecord::Schema.define(version: 20141113134103) do create_table "answers", force: true do |t| t.string "title" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "call_for_papers", force: true do |t| - t.date "start_date", null: false - t.date "end_date", null: false - t.text "description", null: false + t.date "start_date", null: false + t.date "end_date", null: false + t.text "description", limit: 16777215, null: false t.integer "conference_id" - t.datetime "created_at" - t.datetime "updated_at" - t.boolean "schedule_changes", default: false - t.integer "rating", default: 3 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "schedule_changes", default: false + t.integer "rating", default: 3 t.boolean "schedule_public" - t.boolean "include_cfp_in_splash", default: false + t.boolean "include_cfp_in_splash", default: false end create_table "campaigns", force: true do |t| @@ -57,13 +57,13 @@ ActiveRecord::Schema.define(version: 20141113134103) do end create_table "comments", force: true do |t| - t.string "title", limit: 50, default: "" - t.text "body" + t.string "title", limit: 50, default: "" + t.text "body", limit: 16777215 t.integer "commentable_id" t.string "commentable_type" t.integer "user_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "subject" t.integer "parent_id" t.integer "lft" @@ -91,9 +91,8 @@ ActiveRecord::Schema.define(version: 20141113134103) do t.string "html_export_path" t.date "start_date", null: false t.date "end_date", null: false - t.integer "venue_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "logo_file_name" t.string "logo_content_type" t.integer "logo_file_size" @@ -106,6 +105,7 @@ ActiveRecord::Schema.define(version: 20141113134103) do t.boolean "use_volunteers" t.string "color" t.text "events_per_week" + t.text "description" end create_table "conferences_questions", id: false, force: true do |t| @@ -145,8 +145,8 @@ ActiveRecord::Schema.define(version: 20141113134103) do create_table "dietary_choices", force: true do |t| t.integer "conference_id" t.string "title", null: false - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "difficulty_levels", force: true do |t| @@ -154,37 +154,37 @@ ActiveRecord::Schema.define(version: 20141113134103) do t.string "title" t.text "description" t.string "color" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "email_settings", force: true do |t| t.integer "conference_id" - t.boolean "send_on_registration", default: false - t.boolean "send_on_accepted", default: false - t.boolean "send_on_rejected", default: false - t.boolean "send_on_confirmed_without_registration", default: false - t.text "registration_email_template" - t.text "accepted_email_template" - t.text "rejected_email_template" - t.text "confirmed_email_template" - t.datetime "created_at" - t.datetime "updated_at" + t.boolean "send_on_registration", default: false + t.boolean "send_on_accepted", default: false + t.boolean "send_on_rejected", default: false + t.boolean "send_on_confirmed_without_registration", default: false + t.text "registration_email_template", limit: 16777215 + t.text "accepted_email_template", limit: 16777215 + t.text "rejected_email_template", limit: 16777215 + t.text "confirmed_email_template", limit: 16777215 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "registration_subject" t.string "accepted_subject" t.string "rejected_subject" t.string "confirmed_without_registration_subject" - t.boolean "send_on_updated_conference_dates", default: false + t.boolean "send_on_updated_conference_dates", default: false t.string "updated_conference_dates_subject" t.text "updated_conference_dates_template" - t.boolean "send_on_updated_conference_registration_dates", default: false + t.boolean "send_on_updated_conference_registration_dates", default: false t.string "updated_conference_registration_dates_subject" t.text "updated_conference_registration_dates_template" - t.boolean "send_on_venue_update", default: false + t.boolean "send_on_venue_update", default: false t.string "venue_update_subject" t.text "venue_update_template" - t.boolean "send_on_call_for_papers_dates_updates", default: false - t.boolean "send_on_call_for_papers_schedule_public", default: false + t.boolean "send_on_call_for_papers_dates_updates", default: false + t.boolean "send_on_call_for_papers_schedule_public", default: false t.string "call_for_papers_schedule_public_subject" t.string "call_for_papers_dates_updates_subject" t.text "call_for_papers_schedule_public_template" @@ -193,14 +193,14 @@ ActiveRecord::Schema.define(version: 20141113134103) do create_table "event_attachments", force: true do |t| t.integer "event_id" - t.string "title", null: false + t.string "title", null: false t.string "attachment_file_name" t.string "attachment_content_type" t.integer "attachment_file_size" t.datetime "attachment_updated_at" - t.boolean "public", default: false - t.datetime "created_at" - t.datetime "updated_at" + t.boolean "public", default: true + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "event_types", force: true do |t| @@ -222,28 +222,28 @@ ActiveRecord::Schema.define(version: 20141113134103) do end create_table "events", force: true do |t| - t.string "guid", null: false + t.string "guid", null: false t.integer "conference_id" t.integer "event_type_id" - t.string "title", null: false + t.string "title", null: false t.string "subtitle" t.integer "time_slots" - t.string "state", default: "new", null: false - t.string "progress", default: "new", null: false + t.string "state", default: "new", null: false + t.string "progress", default: "new", null: false t.string "language" t.datetime "start_time" - t.text "abstract" - t.text "description" - t.boolean "public", default: true + t.text "abstract", limit: 16777215 + t.text "description", limit: 16777215 + t.boolean "public", default: true t.string "logo_file_name" t.string "logo_content_type" t.integer "logo_file_size" t.datetime "logo_updated_at" - t.text "proposal_additional_speakers" + t.text "proposal_additional_speakers", limit: 16777215 t.integer "track_id" t.integer "room_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.boolean "require_registration" t.integer "difficulty_level_id" t.integer "week" @@ -261,10 +261,10 @@ ActiveRecord::Schema.define(version: 20141113134103) do t.string "photo_content_type" t.integer "photo_file_size" t.datetime "photo_updated_at" - t.integer "venue_id" t.datetime "created_at" t.datetime "updated_at" t.string "website_link" + t.integer "conference_id" end create_table "openids", force: true do |t| @@ -276,6 +276,29 @@ ActiveRecord::Schema.define(version: 20141113134103) do t.datetime "updated_at" end + create_table "people", force: true do |t| + t.string "guid", null: false + t.text "first_name" + t.text "last_name" + t.text "public_name" + t.text "company" + t.string "email", null: false + t.boolean "email_public" + t.string "avatar_file_name" + t.string "avatar_content_type" + t.integer "avatar_file_size" + t.datetime "avatar_updated_at" + t.text "biography" + t.integer "user_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "irc_nickname" + t.text "volunteer_experience" + t.string "tshirt" + t.string "mobile" + t.string "languages" + end + create_table "photos", force: true do |t| t.text "description" t.string "picture_file_name" @@ -299,8 +322,8 @@ ActiveRecord::Schema.define(version: 20141113134103) do create_table "question_types", force: true do |t| t.string "title" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "questions", force: true do |t| @@ -308,8 +331,8 @@ ActiveRecord::Schema.define(version: 20141113134103) do t.integer "question_type_id" t.integer "conference_id" t.boolean "global" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "registration_periods", force: true do |t| @@ -324,12 +347,12 @@ ActiveRecord::Schema.define(version: 20141113134103) do t.integer "conference_id" t.datetime "arrival" t.datetime "departure" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.integer "dietary_choice_id" - t.text "other_dietary_choice" - t.text "other_special_needs" - t.boolean "attended", default: false + t.text "other_dietary_choice", limit: 16777215 + t.text "other_special_needs", limit: 16777215 + t.boolean "attended", default: false t.boolean "volunteer" t.integer "user_id" t.integer "week" @@ -347,8 +370,8 @@ ActiveRecord::Schema.define(version: 20141113134103) do create_table "roles", force: true do |t| t.string "name" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "description" t.integer "resource_id" t.string "resource_type" @@ -385,21 +408,11 @@ ActiveRecord::Schema.define(version: 20141113134103) do t.boolean "include_tracks" t.boolean "include_program" t.boolean "include_social_media" - t.boolean "include_banner" t.boolean "include_venue" t.boolean "include_tickets" - t.text "ticket_description" t.boolean "include_registrations" - t.text "registration_description" t.boolean "include_sponsors" - t.text "sponsor_description" t.boolean "include_lodgings" - t.text "lodging_description" - t.text "banner_description" - t.string "banner_photo_file_name" - t.string "banner_photo_content_type" - t.integer "banner_photo_file_size" - t.datetime "banner_photo_updated_at" t.datetime "created_at" t.datetime "updated_at" end @@ -461,13 +474,13 @@ ActiveRecord::Schema.define(version: 20141113134103) do end create_table "tracks", force: true do |t| - t.string "guid", null: false + t.string "guid", null: false t.integer "conference_id" - t.string "name", null: false - t.text "description" + t.string "name", null: false + t.text "description", limit: 16777215 t.string "color" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "users", force: true do |t| @@ -485,8 +498,8 @@ ActiveRecord::Schema.define(version: 20141113134103) do t.datetime "confirmed_at" t.datetime "confirmation_sent_at" t.string "unconfirmed_email" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "name" t.boolean "email_public" t.text "biography" @@ -519,33 +532,37 @@ ActiveRecord::Schema.define(version: 20141113134103) do t.integer "conference_id" t.date "day" t.text "description" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "venues", force: true do |t| t.string "guid" - t.text "name", limit: 255 - t.text "address", limit: 255 + t.string "name" t.string "website" t.text "description" - t.string "offline_map_url" - t.string "offline_map_bounds" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "photo_file_name" t.string "photo_content_type" t.integer "photo_file_size" t.datetime "photo_updated_at" + t.string "street" + t.integer "postalcode" + t.string "city" + t.string "country" + t.string "latitude" + t.string "longitude" + t.integer "conference_id" end create_table "versions", force: true do |t| - t.string "item_type", null: false - t.integer "item_id", null: false - t.string "event", null: false + t.string "item_type", null: false + t.integer "item_id", null: false + t.string "event", null: false t.string "whodunnit" - t.text "object" - t.text "object_changes" + t.text "object", limit: 16777215 + t.text "object_changes", limit: 16777215 t.datetime "created_at" end @@ -579,8 +596,8 @@ ActiveRecord::Schema.define(version: 20141113134103) do create_table "votes", force: true do |t| t.integer "event_id" t.integer "rating" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.integer "user_id" end @@ -588,8 +605,8 @@ ActiveRecord::Schema.define(version: 20141113134103) do t.integer "conference_id" t.string "title", null: false t.text "description" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end end diff --git a/spec/factories/lodgings.rb b/spec/factories/lodgings.rb index efa16bb2..00553f78 100644 --- a/spec/factories/lodgings.rb +++ b/spec/factories/lodgings.rb @@ -5,6 +5,5 @@ FactoryGirl.define do name 'Example Hotel' description 'Lorem Ipsum Dolor' website_link 'http://www.example.com' - venue end end diff --git a/spec/factories/venues.rb b/spec/factories/venues.rb index 69eb863b..190f4600 100644 --- a/spec/factories/venues.rb +++ b/spec/factories/venues.rb @@ -2,7 +2,10 @@ FactoryGirl.define do factory :venue do name 'Suse Office' - address 'Maxfeldstrasse 5 \n90409 Nuremberg' + street 'Maxfeldstrasse 5' + city 'Nuremberg' + postalcode '90489' + country 'DE' website 'www.opensuse.org' description 'Lorem Ipsum Dolor' end diff --git a/spec/features/ability_spec.rb b/spec/features/ability_spec.rb index 3549cc25..28b30b70 100644 --- a/spec/features/ability_spec.rb +++ b/spec/features/ability_spec.rb @@ -29,7 +29,7 @@ feature 'Has correct abilities' do expect(page).to have_link('Schedule', href: "/admin/conference/#{conference1.short_title}/schedule") expect(page).to have_link('Campaigns', href: "/admin/conference/#{conference1.short_title}/campaigns") expect(page).to have_link('Goals', href: "/admin/conference/#{conference1.short_title}/targets") - expect(page).to have_link('Venue', href: "/admin/conference/#{conference1.short_title}/venue/edit") + expect(page).to have_link('Venue', href: "/admin/conference/#{conference1.short_title}/venue") expect(page).to have_link('Rooms', href: "/admin/conference/#{conference1.short_title}/rooms") expect(page).to have_link('Lodgings', href: "/admin/conference/#{conference1.short_title}/lodgings") expect(page).to have_link('Sponsorship', href: "/admin/conference/#{conference1.short_title}/sponsorship_levels") @@ -100,7 +100,7 @@ feature 'Has correct abilities' do expect(page).to have_link('Schedule', href: "/admin/conference/#{conference2.short_title}/schedule") expect(page).to_not have_link('Campaigns', href: "/admin/conference/#{conference2.short_title}/campaigns") expect(page).to_not have_link('Goals', href: "/admin/conference/#{conference2.short_title}/targets") - expect(page).to have_link('Venue', href: "/admin/conference/#{conference2.short_title}/venue/edit") + expect(page).to have_link('Venue', href: "/admin/conference/#{conference2.short_title}/venue") expect(page).to have_link('Rooms', href: "/admin/conference/#{conference2.short_title}/rooms") expect(page).to_not have_link('Lodgings', href: "/admin/conference/#{conference2.short_title}/lodgings") expect(page).to_not have_link('Sponsorship', href: "/admin/conference/#{conference2.short_title}/sponsorship_levels") @@ -171,7 +171,7 @@ feature 'Has correct abilities' do expect(page).to_not have_link('Schedule', href: "/admin/conference/#{conference3.short_title}/schedule") expect(page).to_not have_link('Campaigns', href: "/admin/conference/#{conference3.short_title}/campaigns") expect(page).to_not have_link('Targets', href: "/admin/conference/#{conference3.short_title}/targets") - expect(page).to_not have_link('Venue', href: "/admin/conference/#{conference3.short_title}/venue/edit") + expect(page).to_not have_link('Venue', href: "/admin/conference/#{conference3.short_title}/venue") expect(page).to_not have_link('Rooms', href: "/admin/conference/#{conference3.short_title}/rooms") expect(page).to_not have_link('Lodgings', href: "/admin/conference/#{conference3.short_title}/lodgings") expect(page).to_not have_link('Sponsorship', href: "/admin/conference/#{conference3.short_title}/sponsorship_levels") @@ -243,7 +243,7 @@ feature 'Has correct abilities' do expect(page).to_not have_link('Schedule', href: "/admin/conference/#{conference4.short_title}/schedule") expect(page).to_not have_link('Campaigns', href: "/admin/conference/#{conference4.short_title}/campaigns") expect(page).to_not have_link('Goals', href: "/admin/conference/#{conference4.short_title}/targets") - expect(page).to_not have_link('Venue', href: "/admin/conference/#{conference4.short_title}/venue/edit") + expect(page).to_not have_link('Venue', href: "/admin/conference/#{conference4.short_title}/venue") expect(page).to_not have_link('Rooms', href: "/admin/conference/#{conference4.short_title}/rooms") expect(page).to_not have_link('Lodgings', href: "/admin/conference/#{conference4.short_title}/lodgings") expect(page).to_not have_link('Sponsorship', href: "/admin/conference/#{conference4.short_title}/sponsorship_levels") diff --git a/spec/features/lodgings_spec.rb b/spec/features/lodgings_spec.rb index 069d2e6c..44ec0fad 100644 --- a/spec/features/lodgings_spec.rb +++ b/spec/features/lodgings_spec.rb @@ -8,7 +8,6 @@ feature Lodging do scenario 'Add a lodging', feature: true, js: true do path = "#{Rails.root}/app/assets/images/rails.png" - conference.venue = create(:venue) sign_in organizer visit admin_conference_lodgings_path( conference_id: conference.short_title) @@ -16,7 +15,6 @@ feature Lodging do click_link 'Add Lodging' fill_in 'lodging_name', with: 'New lodging' - fill_in 'lodging_description', with: 'This is the lodging description' fill_in 'lodging_website_link', with: 'http:\\www.google.com' attach_file 'Photo', path @@ -25,17 +23,13 @@ feature Lodging do # Validations expect(flash).to eq('Lodging successfully created.') expect(page.has_content?('New lodging')).to be true - expect(page.has_content?('This is the lodging description')).to be true - expect(page.has_content?('Go to Website')).to be true expect(Lodging.count).to eq(1) end scenario 'Update a lodging', feature: true, js: true do path = "#{Rails.root}/app/assets/images/rails.png" - venue = create(:venue) - lodging = create(:lodging, venue: conference.venue) - conference.venue = venue + lodging = create(:lodging, conference: conference) sign_in organizer visit admin_conference_lodgings_path( @@ -48,7 +42,6 @@ feature Lodging do click_link 'Edit' fill_in 'lodging_name', with: 'New lodging' - fill_in 'lodging_description', with: 'This is the lodging description' fill_in 'lodging_website_link', with: 'http:\\www.google.com' attach_file 'Photo', path @@ -57,19 +50,15 @@ feature Lodging do # Validations expect(flash).to eq('Lodging successfully updated.') expect(page.has_content?('New lodging')).to be true - expect(page.has_content?('This is the lodging description')).to be true - expect(page.has_content?('Go to Website')).to be true lodging.reload expect(lodging.name).to eq('New lodging') - expect(lodging.description).to eq('This is the lodging description') + expect(lodging.description).to eq('Lorem Ipsum Dolor') expect(lodging.website_link).to eq('http:\\www.google.com') expect(Lodging.count).to eq(1) end scenario 'Delete a lodging', feature: true, js: true do - venue = create(:venue) - create(:lodging, venue: conference.venue) - conference.venue = venue + conference.lodgings << create(:lodging) sign_in organizer visit admin_conference_lodgings_path( diff --git a/spec/features/splashpage_spec.rb b/spec/features/splashpage_spec.rb index f6f7ffc4..8b5dd122 100644 --- a/spec/features/splashpage_spec.rb +++ b/spec/features/splashpage_spec.rb @@ -13,33 +13,13 @@ feature Splashpage do visit admin_conference_splashpage_path(conference.short_title) click_link 'Create Splashpage' - - fill_in 'splashpage_banner_description', with: 'banner description' - fill_in 'splashpage_ticket_description', with: 'ticket description' - fill_in 'splashpage_sponsor_description', with: 'sponsor description' - fill_in 'splashpage_registration_description', with: 'registration description' - fill_in 'splashpage_lodging_description', with: 'lodging description' - click_button 'Save Splashpage' expect(flash).to eq('Splashpage successfully created.') expect(current_path).to eq(admin_conference_splashpage_path(conference.short_title)) - - splashpage = Splashpage.find_by(conference_id: conference.id) - splashpage.reload - expect(splashpage.banner_description).to eq('banner description') - expect(splashpage.ticket_description).to eq('ticket description') - expect(splashpage.sponsor_description).to eq('sponsor description') - expect(splashpage.registration_description).to eq('registration description') - expect(splashpage.lodging_description).to eq('lodging description') end context 'splashpage already created' do - # before(:each) do - # @splashpage = create(:splashpage) - # conference.splashpage = @splashpage - # end - # let!(:splashpage) { create(:splashpage, conference: conference, public: false)} scenario 'update a valid splashpage', js: true do @@ -47,24 +27,14 @@ feature Splashpage do visit admin_conference_splashpage_path(conference.short_title) click_link 'Edit' - - fill_in 'splashpage_banner_description', with: 'banner description' - fill_in 'splashpage_ticket_description', with: 'ticket description' - fill_in 'splashpage_sponsor_description', with: 'sponsor description' - fill_in 'splashpage_registration_description', with: 'registration description' - fill_in 'splashpage_lodging_description', with: 'lodging description' - + check('Make splash page public') click_button 'Save Splashpage' expect(flash).to eq('Splashpage successfully updated.') expect(current_path).to eq(admin_conference_splashpage_path(conference.short_title)) - splashpage.reload - expect(splashpage.banner_description).to eq('banner description') - expect(splashpage.ticket_description).to eq('ticket description') - expect(splashpage.sponsor_description).to eq('sponsor description') - expect(splashpage.registration_description).to eq('registration description') - expect(splashpage.lodging_description).to eq('lodging description') + click_link 'Edit' + expect(page.has_checked_field?('Make splash page public?')).to be true end scenario 'delete the splashpage', js: true do diff --git a/spec/features/venues_spec.rb b/spec/features/venues_spec.rb index 4489afea..fa8e98f1 100644 --- a/spec/features/venues_spec.rb +++ b/spec/features/venues_spec.rb @@ -17,8 +17,10 @@ feature Conference do text).to eq('Update Venue') fill_in 'venue_name', with: 'Example University' - fill_in 'venue_address', with: 'Example Street 42 \n' + - '12345 Example City \n Germany' + fill_in 'venue_street', with: 'Example Street 42' + fill_in 'venue_city', with: 'Example City' + fill_in 'venue_postalcode', with: '12345' + select 'Germany', from: 'venue_country' fill_in 'venue_website', with: 'www.example.com' fill_in 'venue_description', with: 'Lorem ipsum dolor sit amet, consetetur' \ @@ -31,15 +33,13 @@ feature Conference do venue = Conference.find(conference.id).venue expect(venue.name).to eq('Example University') - expect(venue.address).to eq('Example Street 42 \n' \ - '12345 Example City \n Germany') + expect(venue.street).to eq('Example Street 42') expect(venue.website).to eq('www.example.com') expect(venue.description).to eq('Lorem ipsum dolor sit amet, consetetur' \ 'sadipscing elitr, sed diam nonumy eirmod tempor') + click_link 'Edit Venue' fill_in 'venue_name', with: 'Example University new' - fill_in 'venue_address', with: 'Example Street 42 \n ' \ - '12345 Example City \n Germany new' fill_in 'venue_website', with: 'www.example.com new' fill_in 'venue_description', with: 'new' @@ -50,8 +50,6 @@ feature Conference do venue.reload expect(venue.name).to eq('Example University new') - expect(venue.address).to eq('Example Street 42 \n ' \ - '12345 Example City \n Germany new') expect(venue.website).to eq('www.example.com new') expect(venue.description).to eq('new') end diff --git a/spec/models/conference_spec.rb b/spec/models/conference_spec.rb index 3cdfc183..6c06ff1a 100644 --- a/spec/models/conference_spec.rb +++ b/spec/models/conference_spec.rb @@ -980,6 +980,7 @@ describe Conference do start_date: Date.today, end_date: Date.today + 14) subject.call_for_papers = nil + subject.venue = nil subject.rooms = [] subject.tracks = [] subject.event_types = [] @@ -997,6 +998,7 @@ describe Conference do start_date: Date.today, end_date: Date.today + 14) subject.call_for_papers = create(:call_for_papers) + subject.venue = nil subject.rooms = [] subject.tracks = [] subject.event_types = [] diff --git a/spec/views/admin/lodgings/index.html.haml_spec.rb b/spec/views/admin/lodgings/index.html.haml_spec.rb index 60d93d0d..bb20da17 100644 --- a/spec/views/admin/lodgings/index.html.haml_spec.rb +++ b/spec/views/admin/lodgings/index.html.haml_spec.rb @@ -4,7 +4,7 @@ describe 'admin/lodgings/index' do it 'renders lodgings list' do @conference = create(:conference) @conference.venue = create(:venue) - @conference.venue.lodgings << create(:lodging, venue: @conference.venue) + @conference.lodgings << create(:lodging) assign :venue, @conference.venue render expect(rendered).to include('Example Hotel') diff --git a/spec/views/admin/venues/edit.html.haml_spec.rb b/spec/views/admin/venues/edit.html.haml_spec.rb deleted file mode 100644 index a4bc62a4..00000000 --- a/spec/views/admin/venues/edit.html.haml_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -require 'spec_helper' - -describe 'admin/venues/edit' do - - it 'renders venues#show' do - @conference = create(:conference) - @venue = @conference.venue - @venue.name = 'Croatia' - @venue.description = 'Lorem ipsum dolsum' - @venue.save! - assign :conference, @conference - assign :venue, @venue - render - expect(rendered).to include('Croatia') - expect(rendered).to include('Lorem ipsum dolsum') - end -end diff --git a/spec/views/conference/show.html.haml_spec.rb b/spec/views/conference/show.html.haml_spec.rb index 43f28b21..0b705fd3 100644 --- a/spec/views/conference/show.html.haml_spec.rb +++ b/spec/views/conference/show.html.haml_spec.rb @@ -2,18 +2,14 @@ require 'spec_helper' describe 'conference/show.html.haml' do before(:each) do allow(view).to receive(:date_string).and_return('January 17 - 21 2014') - @conference = create(:conference) + @conference = create(:conference, description: 'Lorem Ipsum') @conference.splashpage = create(:splashpage, - banner_description: 'Banner Description', - sponsor_description: 'Sponsor Description', - registration_description: 'Registration Description', include_registrations: true, include_program: true, include_sponsors: true, include_tracks: true, include_tickets: true, - include_banner: true, include_social_media: true, include_venue: true, include_lodgings: true) @@ -37,14 +33,13 @@ describe 'conference/show.html.haml' do conference: @conference) @conference.venue = create(:venue) - @conference.venue.lodgings << create(:lodging, venue: @conference.venue) + @conference.lodgings << create(:lodging) assign :conference, @conference render end it 'renders banner component' do - expect(rendered).to match(/#{@conference.splashpage.banner_description}/) - expect(rendered).to match(/#{@conference.short_title}/) + expect(rendered).to match(/#{@conference.description}/) end it 'renders program partial' do @@ -56,13 +51,12 @@ describe 'conference/show.html.haml' do end it 'renders call_for_papers partial' do - expect(rendered).to match(/#{@conference.call_for_papers.description}/) + expect(rendered).to match(/We are ready to accept your proposals for sessions!/) end it 'renders sponsors partial' do expect(view).to render_template(partial: 'conference/_sponsors') expect(rendered).to match(/example@example.com/) - expect(rendered).to match(/Platin/) expect(rendered).to match(/Example sponsor/) expect(rendered).to match(/www.example.com/) expect(rendered).to match(/Lorem Ipsum Dolor/) @@ -77,8 +71,8 @@ describe 'conference/show.html.haml' do expect(rendered).to match(/twitter.com/) end - it 'renders location partial' do - expect(view).to render_template(partial: 'conference/_location') + it 'renders venue partial' do + expect(view).to render_template(partial: 'conference/_venue') expect(rendered).to match(/Suse Office/) expect(rendered).to match(/Maxfeldstrasse 5/) expect(rendered).to match(/www.opensuse.org/)