Skip to content

Commit

Permalink
Merge branch 'release/8.5'
Browse files Browse the repository at this point in the history
  • Loading branch information
smoyte committed Jan 18, 2022
2 parents 8877d2b + b97954e commit a27ee9a
Show file tree
Hide file tree
Showing 92 changed files with 1,658 additions and 1,322 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8.4.2
8.5
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Gather.Views.Calendars.CalendarListView = Backbone.View.extend
initialize: (options) ->
@selection = options.selection || {}
@dontPersist = options.dontPersist || false
@loadSelection()

events:
Expand All @@ -14,7 +15,11 @@ Gather.Views.Calendars.CalendarListView = Backbone.View.extend
selectedIds: ->
@$("input[type=checkbox]:checked").map((_, el) -> el.value).get()

allSelected: ->
@$("input[type=checkbox]").get().every((el) => @$(el).is(":checked"))

saveSelection: ->
return if @dontPersist
entries = @$("input[type=checkbox]").map((_, el) => [[el.value, @$(el).prop('checked')]])
@selection = Object.fromEntries(entries)
Gather.loadingIndicator.show()
Expand Down
69 changes: 69 additions & 0 deletions app/assets/javascripts/backbone/views/calendars/export_view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
Gather.Views.Calendars.ExportView = class ExportView extends Backbone.View {
initialize(options) {
this.listView = options.listView;
this.communityToken = options.communityToken;
this.userToken = options.userToken;
this.rootUrl = options.rootUrl;
this.rebuildUrl();
}

get events() {
return {
"click .calendar-list-wrapper input": "rebuildUrl",
"click #calendars_export_dont_personalize": "rebuildUrl",
"click #calendars_export_own_only": "rebuildUrl",
"click #copy-link": "copyLink",
"click #visit-link": "visitLink"
};
}

rebuildUrl() {
const base = this.rootUrl.replace(/https?:/, "webcal:");
let params = [];
params.push(`calendars=${this.calendarIds}`);
params.push(`token=${this.token}`);
if (this.personalized && this.ownOnly) {
params.push("own_only=1");
}
this.$("#export-url").val(`${base}${this.path}?${params.join("&")}`);
this.toggleOwnOnlyCheckbox();
}

get calendarIds() {
return this.listView.allSelected() ? "all" : this.listView.selectedIds().join("+");
}

get path() {
return this.personalized ? "calendars/export.ics" : "calendars/community-export.ics";
}

get token() {
return this.personalized ? this.userToken : this.communityToken;
}

get personalized() {
return !this.$("#calendars_export_dont_personalize").is(":checked");
}

get ownOnly() {
return this.$("#calendars_export_own_only").is(":checked");
}

get url() {
return this.$("#export-url").val();
}

copyLink(event) {
copyTextToClipboard(this.url);
event.preventDefault();
}

visitLink(event) {
window.location.href = this.url;
event.preventDefault();
}

toggleOwnOnlyCheckbox() {
this.$(".form-group.calendars_export_own_only").toggle(this.personalized);
}
};
15 changes: 8 additions & 7 deletions app/assets/stylesheets/global/text.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ p.intro {
font-size: 16px;
}

small {
font-size: 12px;
@mixin deemphasized-text {
font-size: 13px;
color: $text-muted;
line-height: 1.4;
}

small {
@include deemphasized-text;
display: block;

a {
Expand All @@ -18,10 +23,6 @@ small {
}

.footnote {
@include deemphasized-text;
margin-top: 10px;

&.footnote-small {
font-size: 13px;
line-height: 1.6;
}
}
7 changes: 0 additions & 7 deletions app/assets/stylesheets/global/theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,6 @@ p.inner {
margin-top: $large-margin;
}

.footnote {
margin-top: 10px;
font-size: 13px;
color: $text-muted;
line-height: 1.4;
}

.datetimepicker .input-group-btn > .btn-default {
border: 1px solid $btn-default-border;
}
Expand Down
9 changes: 7 additions & 2 deletions app/assets/stylesheets/local/calendars/calendar_list.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.calendar-list-with-links {
.calendar-list-wrapper {
.links {
a {
font-size: 13px;
Expand All @@ -14,11 +14,16 @@
font-size: 1.3rem;
}

.calendar {
.calendar, .calendar label {
display: flex;
align-items: center;
}

label {
font-weight: normal;
margin-bottom: 0;
}

a.calendar-link {
white-space: nowrap;
overflow: hidden;
Expand Down
43 changes: 24 additions & 19 deletions app/assets/stylesheets/local/calendars/exports.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,34 @@ div.title-and-buttons div.top-buttons a.calendar-export {
}

.calendars--exports.action-index {
.links {
margin-bottom: 20px;

div {
font-size: 1.1em;
line-height: 1.1em;
margin-bottom: 10px;

i.fa {
color: $text-muted;
margin: 0 10px 0 20px;
}
#export-url {
font-size: 1.1em;
line-height: 1.1em;
padding: 5px;
width: 100%;
}

ol {
padding-left: 14px;
}

@media screen and (min-width: $screen-sm-min) {
.calendars-and-url {
display: flex;
}

a.copy {
display: inline-block;
margin-left: 49px;
color: $text-muted;
font-size: 0.7em;
.calendar-list-wrapper {
margin-right: 30px;
}

.calendar-list-wrapper h2 {
display: none;
}
}

ol {
padding-left: 14px;
.options {
.checkbox {
margin-bottom: 0;
}
}
}
2 changes: 1 addition & 1 deletion app/controllers/calendars/events_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def prep_combined_index(calendar_scope)
prepare_lenses(*[community: {clearable: false}].concat(BASE_LENSES))
@rule_set_serializer = {}
@can_create_event = writeable_calendars.any?
setting = current_user.settings[:calendar_selection]
setting = current_user.settings["calendar_selection"]
@calendar_selection = InitialSelection.new(stored: setting, calendar_scope: calendar_scope).selection

@new_event_path = new_calendars_event_path(origin_page: "combined")
Expand Down
86 changes: 51 additions & 35 deletions app/controllers/calendars/exports_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,69 +3,85 @@
module Calendars
# Calendar exports
class ExportsController < ApplicationController
# Users are authenticated from the provided token for the personalized endpoint.
prepend_before_action :authenticate_user_from_token!, only: :personalized
include Exportable

# This is skipped to support legacy domains.
skip_before_action :ensure_subdomain, only: :personalized
# Users are authenticated from the provided token for the personalized endpoint.
prepend_before_action :authenticate_user_from_calendar_token!, only: :personalized

# Community calendars are not user-specific. Authorization is handled by the policy class
# based on the community calendar token.
skip_before_action :authenticate_user!, only: :community
# Authentication happens via token and community calendars aren't user-authenticated.
skip_before_action :authenticate_user!, only: :nonpersonalized

def index
skip_policy_scope
authorize(sample_export, policy_class: ExportPolicy)
authorize(current_community, policy_class: ExportPolicy)
current_user.ensure_calendar_token!
load_calendar_selection
end

def community
export = Exports::Factory.build(type: params[:id], community: current_community)
policy = ExportPolicy.new(nil, export, community_token: params[:calendar_token])
authorize_with_explict_policy_object(export, :community?, policy_object: policy)
send_calendar_data(export)
rescue Exports::TypeError
handle_calendar_error
def personalized
authorize(current_community, :personalized?, policy_class: ExportPolicy)
finder = EventFinder.new(calendars: calendars, range: event_date_range,
user: current_user, own_only: params[:own_only] == "1")
send_calendar_data(calendar_name, finder.events)
end

def personalized
export = Exports::Factory.build(type: params[:id], user: current_user)
authorize(export, policy_class: ExportPolicy)
send_calendar_data(export)
rescue Exports::TypeError
handle_calendar_error
# Nonpersonalized exports are those where the current user is not known and the token
# specifies the community only.
# current_community comes from the URL subdomain.
def nonpersonalized
policy = ExportPolicy.new(nil, current_community, community_token: params[:token])
authorize_with_explict_policy_object(:community?, policy_object: policy)
finder = EventFinder.new(calendars: calendars, range: event_date_range,
user: nil, own_only: false)
send_calendar_data(calendar_name, finder.events)
end

def reset_token
authorize(sample_export, policy_class: ExportPolicy)
authorize(current_community, policy_class: ExportPolicy)
current_user.reset_calendar_token!
flash[:success] = "Token reset successfully."
redirect_to(calendars_exports_path)
end

protected

# See def'n in ApplicationController for documentation.
def community_for_route
case params[:action]
when "index", "personalized"
current_user.community
end
def export_file_basename
"calendars"
end

private

def sample_export
Exports::Export.new(user: current_user)
def load_calendar_selection
calendar_scope = policy_scope(Node).in_community(current_community).active
@calendars = calendar_scope.arrange(decorator: CalendarDecorator)
@calendar_selection =
# If a single calendar is requested, honor that.
if params[:calendar_id]
{params[:calendar_id] => true}
else
setting = current_user.settings["calendar_selection"]
InitialSelection.new(stored: setting, calendar_scope: calendar_scope).selection
end
end

def send_calendar_data(export)
send_data(export.generate, filename: "#{params[:id]}.ics", type: "text/calendar")
def calendars
return @calendars if @calendars
calendar_scope = Calendar.in_community(current_community)
@calendars = if params[:calendars] == "all"
calendar_scope.to_a
else
calendar_scope.where(id: params[:calendars].split(" ")).to_a
end
end

def handle_calendar_error
skip_authorization # Auth may not have been performed yet but that's OK b/c we're erroring.
render(plain: "Invalid calendar type", status: :not_found)
def calendar_name
if params[:calendars] == "all"
"All #{current_community.abbrv} Calendars"
elsif calendars.size == 1
"#{current_community.abbrv} #{calendars[0].name}"
else
"#{calendars.size} #{current_community.abbrv} Calendars"
end
end
end
end
Loading

0 comments on commit a27ee9a

Please sign in to comment.