mirror of
https://github.com/wekan/wekan.git
synced 2025-04-23 21:47:10 -04:00
Upgrade sandstorm integration
Both sandstorm and LibreBoard have significantly evolved since the last release of LibreBoard on sandstorm. This commit: * adds some more attributes on the sandstorm manifest * introduces support with the sandstorm sharing box * uses a server redirection to point to the board document * hides the top shortcut bar on sandstorm Fixes #163.
This commit is contained in:
parent
fc2435b042
commit
1b4fcc67f4
7 changed files with 142 additions and 82 deletions
|
@ -70,7 +70,7 @@ BlazeComponent.extendComponent({
|
|||
}
|
||||
};
|
||||
|
||||
if (! Meteor.user().isBoardMember())
|
||||
if (! Meteor.userId() || ! Meteor.user().isBoardMember())
|
||||
return;
|
||||
|
||||
self.$(lists).sortable({
|
||||
|
|
|
@ -5,26 +5,27 @@ template(name="header")
|
|||
list all starred boards with a link to go there. This is inspired by the
|
||||
Reddit "subreddit" bar.
|
||||
The first link goes to the boards page.
|
||||
if currentUser
|
||||
#header-quick-access
|
||||
ul
|
||||
li
|
||||
+linkTo(route="Boards")
|
||||
span.fa.fa-home
|
||||
| All boards
|
||||
each currentUser.starredBoards
|
||||
li.separator -
|
||||
li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}")
|
||||
+linkTo(route="Board" data=this)
|
||||
= title
|
||||
else
|
||||
li.current Star a board to add a shortcut in this bar.
|
||||
unless isSandstorm
|
||||
if currentUser
|
||||
#header-quick-access
|
||||
ul
|
||||
li
|
||||
+linkTo(route="Boards")
|
||||
span.fa.fa-home
|
||||
| All boards
|
||||
each currentUser.starredBoards
|
||||
li.separator -
|
||||
li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}")
|
||||
+linkTo(route="Board" data=this)
|
||||
= title
|
||||
else
|
||||
li.current Star a board to add a shortcut in this bar.
|
||||
|
||||
li
|
||||
a.js-create-board
|
||||
i.fa.fa-plus(title="Create a new board")
|
||||
li
|
||||
a.js-create-board
|
||||
i.fa.fa-plus(title="Create a new board")
|
||||
|
||||
+headerUserBar
|
||||
+headerUserBar
|
||||
|
||||
//-
|
||||
The main bar is a colorful bar that provide all the meta-data for the
|
||||
|
|
|
@ -48,7 +48,7 @@ BlazeComponent.extendComponent({
|
|||
|
||||
onRendered: function() {
|
||||
var self = this;
|
||||
if (! Meteor.user().isBoardMember())
|
||||
if (! Meteor.userId() || ! Meteor.user().isBoardMember())
|
||||
return;
|
||||
|
||||
$(document).on('mouseover', function() {
|
||||
|
|
|
@ -139,7 +139,7 @@ Boards.before.insert(function(userId, doc) {
|
|||
// In some cases (Chinese and Japanese for instance) the `getSlug` function
|
||||
// return an empty string. This is causes bugs in our application so we set
|
||||
// a default slug in this case.
|
||||
doc.slug = getSlug(doc.title) || 'board';
|
||||
doc.slug = doc.slug || getSlug(doc.title) || 'board';
|
||||
doc.createdAt = new Date();
|
||||
doc.archived = false;
|
||||
doc.members = [{
|
||||
|
@ -153,22 +153,13 @@ Boards.before.insert(function(userId, doc) {
|
|||
// Handle labels
|
||||
var colors = Boards.simpleSchema()._schema['labels.$.color'].allowedValues;
|
||||
var defaultLabelsColors = _.clone(colors).splice(0, 6);
|
||||
doc.labels = [];
|
||||
_.each(defaultLabelsColors, function(val) {
|
||||
doc.labels.push({
|
||||
doc.labels = _.map(defaultLabelsColors, function(val) {
|
||||
return {
|
||||
_id: Random.id(6),
|
||||
name: '',
|
||||
color: val
|
||||
});
|
||||
});
|
||||
|
||||
// We randomly chose one of the default background colors for the board
|
||||
if (Meteor.isClient) {
|
||||
doc.background = {
|
||||
type: 'color',
|
||||
color: Random.choice(Boards.simpleSchema()._schema.color.allowedValues)
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Boards.before.update(function(userId, doc, fieldNames, modifier) {
|
||||
|
|
|
@ -33,13 +33,10 @@ Users.helpers({
|
|||
});
|
||||
|
||||
Users.before.insert(function(userId, doc) {
|
||||
doc.profile = {};
|
||||
doc.profile = doc.profile || {};
|
||||
|
||||
// connect profile.status default
|
||||
doc.profile.status = 'offline';
|
||||
|
||||
// slugify to username
|
||||
//doc.username = getSlug(doc.profile.name, '');
|
||||
});
|
||||
|
||||
if (Meteor.isServer) {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# Use use the meteor-spk tool to generate a sandstorm package (spk) from this
|
||||
# meteor application source code. https://github.com/sandstorm-io/meteor-spk
|
||||
@0xa5275bd3ad124e12;
|
||||
|
||||
using Spk = import "/sandstorm/package.capnp";
|
||||
|
@ -10,18 +12,32 @@ const pkgdef :Spk.PackageDefinition = (
|
|||
# "pkgdef" constant.
|
||||
|
||||
id = "m86q05rdvj14yvn78ghaxynqz7u2svw6rnttptxx49g1785cdv1h",
|
||||
# Your app ID is actually its public key. The private key was placed in your
|
||||
# The app ID is actually its public key. The private key was placed in your
|
||||
# keyring. All updates must be signed with the same key.
|
||||
|
||||
manifest = (
|
||||
# This manifest is included in your app package to tell Sandstorm
|
||||
# about your app.
|
||||
# This manifest is included in our app package to tell Sandstorm about our
|
||||
# app.
|
||||
|
||||
appVersion = 1, # Increment this for every release.
|
||||
appTitle = (defaultText = "LibreBoard"),
|
||||
# The name of the app as it is displayed to the user.
|
||||
|
||||
appVersion = 2,
|
||||
# Increment this for every release.
|
||||
|
||||
appMarketingVersion = (defaultText = "0.9.0"),
|
||||
# Human-readable presentation of the app version.
|
||||
|
||||
minUpgradableAppVersion = 0,
|
||||
# The minimum version of the app which can be safely replaced by this app
|
||||
# package without data loss. This might be non-zero if the app's data store
|
||||
# format changed drastically in the past and the app is no longer able to
|
||||
# read the old format.
|
||||
|
||||
actions = [
|
||||
# Define your "new document" handlers here.
|
||||
( title = (defaultText = "New board"),
|
||||
(
|
||||
title = (defaultText = "New board"),
|
||||
command = .myCommand
|
||||
# The command to run when starting for the first time. (".myCommand" is
|
||||
# just a constant defined at the bottom of the file.)
|
||||
|
@ -43,11 +59,43 @@ const pkgdef :Spk.PackageDefinition = (
|
|||
]
|
||||
),
|
||||
|
||||
alwaysInclude = [ "." ]
|
||||
alwaysInclude = [ "." ],
|
||||
# This says that we always want to include all files from the source map. (An
|
||||
# alternative is to automatically detect dependencies by watching what the app
|
||||
# opens while running in dev mode. To see what that looks like, run `spk init`
|
||||
# without the -A option.)
|
||||
|
||||
bridgeConfig = (
|
||||
viewInfo = (
|
||||
permissions = [(
|
||||
name = "participate",
|
||||
title = (defaultText = "participate"),
|
||||
description = (defaultText = "allows participating in the board")
|
||||
), (
|
||||
name = "configure",
|
||||
title = (defaultText = "configure"),
|
||||
description = (defaultText = "allows configuring the board")
|
||||
)],
|
||||
|
||||
roles = [(
|
||||
title = (defaultText = "observer"),
|
||||
permissions = [false, false],
|
||||
verbPhrase = (defaultText = "can read")
|
||||
), (
|
||||
title = (defaultText = "member"),
|
||||
permissions = [true, false],
|
||||
verbPhrase = (defaultText = "can edit"),
|
||||
default = true
|
||||
# ), (
|
||||
# title = (defaultText = "administrator"),
|
||||
# permissions = [true, true],
|
||||
# verbPhrase = (defaultText = "can configure")
|
||||
#
|
||||
# XXX Administrators configuration options aren’t implemented yet, so this
|
||||
# role is currently useless.
|
||||
)]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
const myCommand :Spk.Manifest.Command = (
|
||||
|
|
101
sandstorm.js
101
sandstorm.js
|
@ -8,71 +8,94 @@ var isSandstorm = Meteor.settings && Meteor.settings.public &&
|
|||
// redirect the user to this particular board.
|
||||
var sandstormBoard = {
|
||||
_id: 'sandstorm',
|
||||
slug: 'board',
|
||||
|
||||
// XXX Should be shared with the grain instance name.
|
||||
title: 'LibreBoard',
|
||||
permission: 'public',
|
||||
background: {
|
||||
type: 'color',
|
||||
color: '#16A085'
|
||||
},
|
||||
slug: 'libreboard',
|
||||
|
||||
// XXX Not certain this is a bug, but we except these fields to get inserted
|
||||
// by the `Lists.before.insert` collection-hook. Since this hook is not called
|
||||
// in this case, we have to duplicate the logic and set them here.
|
||||
archived: false,
|
||||
createdAt: new Date()
|
||||
// Board access security is handled by sandstorm, so in our point of view we
|
||||
// can alway assume that the board is public (unauthorized users won’t be able
|
||||
// to access it anyway).
|
||||
permission: 'public'
|
||||
};
|
||||
|
||||
// The list of permissions a user have is provided by sandstorm accounts
|
||||
// package.
|
||||
var userHasPermission = function(user, permission) {
|
||||
var userPermissions = user.services.sandstorm.permissions;
|
||||
return userPermissions.indexOf(permission) > -1;
|
||||
};
|
||||
|
||||
// On the first launch of the instance a user is automatically created thanks to
|
||||
// the `accounts-sandstorm` package. After its creation we insert the unique
|
||||
// board document. Note that when the `Users.after.insert` hook is called, the
|
||||
// user is inserted into the database but not connected. So despite the
|
||||
// appearances `userId` is null in this block.
|
||||
//
|
||||
// If the hard-coded board already exists and we are inserting a new user, we
|
||||
// assume that the owner of the board want to share write privileges with the
|
||||
// new user.
|
||||
// XXX Improve that when the Sandstorm sharing model (“Powerbox”) arrives.
|
||||
if (isSandstorm && Meteor.isServer) {
|
||||
// Redirect the user to the hard-coded board. On the first launch the user
|
||||
// will be redirected to the board before its creation. But that’s not a
|
||||
// problem thanks to the reactive board publication. We used to do this
|
||||
// redirection on the client side but that was sometime visible on loading,
|
||||
// and the home page was accessible by pressing the back button of the
|
||||
// browser, a server-side redirection solves both of these issues.
|
||||
//
|
||||
// XXX Maybe sandstorm manifest could provide some kind of "home url"?
|
||||
Router.route('/', function() {
|
||||
var base = this.request.headers['x-sandstorm-base-path'];
|
||||
// XXX If this routing scheme changes, this will break. We should generation
|
||||
// the location url using the router, but at the time of writting, the
|
||||
// router is only accessible on the client.
|
||||
var path = '/boards/' + sandstormBoard._id + '/' + sandstormBoard.slug;
|
||||
|
||||
this.response.writeHead(301, {
|
||||
Location: base + path
|
||||
});
|
||||
this.response.end();
|
||||
}, { where: 'server' });
|
||||
|
||||
// On the first launch of the instance a user is automatically created thanks
|
||||
// to the `accounts-sandstorm` package. After its creation we insert the
|
||||
// unique board document. Note that when the `Users.after.insert` hook is
|
||||
// called, the user is inserted into the database but not connected. So
|
||||
// despite the appearances `userId` is null in this block.
|
||||
Users.after.insert(function(userId, doc) {
|
||||
if (! Boards.findOne(sandstormBoard._id)) {
|
||||
Boards.insert(_.extend(sandstormBoard, { userId: doc._id }));
|
||||
Boards.insert(sandstormBoard, {validate: false});
|
||||
Boards.update(sandstormBoard._id, {
|
||||
$set: {
|
||||
'members.0.userId': doc._id
|
||||
// The first member (the grain creator) has all rights
|
||||
'members.0': {
|
||||
userId: doc._id,
|
||||
isActive: true,
|
||||
isAdmin: true
|
||||
}
|
||||
}
|
||||
});
|
||||
Activities.update({
|
||||
activityTypeId: sandstormBoard._id
|
||||
}, {
|
||||
$set: {
|
||||
userId: doc._id
|
||||
}
|
||||
Activities.update(
|
||||
{ activityTypeId: sandstormBoard._id }, {
|
||||
$set: { userId: doc._id }
|
||||
});
|
||||
} else {
|
||||
}
|
||||
|
||||
// If the hard-coded board already exists and we are inserting a new user,
|
||||
// we need to update our user collection.
|
||||
else if (userHasPermission(doc, 'participate')) {
|
||||
Boards.update({
|
||||
_id: sandstormBoard._id,
|
||||
permission: 'public'
|
||||
}, {
|
||||
$push: {
|
||||
members: doc._id
|
||||
members: {
|
||||
userId: doc._id,
|
||||
isActive: true,
|
||||
isAdmin: userHasPermission(doc, 'configure')
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// The sandstom user package put the username in `profile.name`. We need to
|
||||
// move this field value to follow our schema.
|
||||
Users.update(doc._id, { $rename: { 'profile.name': 'username' }});
|
||||
});
|
||||
}
|
||||
|
||||
// On the client, redirect the user to the hard-coded board. On the first launch
|
||||
// the user will be redirected to the board before its creation. But that’s not
|
||||
// a problem thanks to the reactive board publication.
|
||||
if (isSandstorm && Meteor.isClient) {
|
||||
Router.go('Board', {
|
||||
boardId: sandstormBoard._id,
|
||||
slug: getSlug(sandstormBoard.title)
|
||||
});
|
||||
|
||||
// XXX Hack. `Meteor.absoluteUrl` doesn't work in Sandstorm, since every
|
||||
// session has a different URL whereas Meteor computes absoluteUrl based on
|
||||
// the ROOT_URL environment variable. So we overwrite this function on a
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue