Commit 1c3904aa authored by Johannes's avatar Johannes

Merge branch 'master' into call-a-bieb-via-store-info

parents 5d9908af cfda1400
Pipeline #42782908 passed with stages
in 13 minutes and 1 second
.pip-cache
vendor
node_modules
chat/node_modules
api
light
.pip-cache
*~
am_cache
.idea
*.swp
......@@ -7,10 +6,8 @@ node_modules
data/**
/data/logg.txt
**/menus/
**/images/
js/gen/script.js
css/gen/style.css
config.inc.php
cache/**
tmp/**
vendor/**
......@@ -20,7 +17,6 @@ tests/_support/_generated/
.composer
chat/.npm
api/**
light/**
.php_cs.cache
.php_cs_cache_local
revision.inc.php
......@@ -30,8 +26,6 @@ migrations/_*
docs/_book
docs/dist
docs/node_modules
.vscode
.views-cache
assets
dev-assets
client/.env
......@@ -41,3 +35,4 @@ client/.yarnrc
client/dist
client/test/_compiled.js
c3.php
/images/
# Unreleased
## Features
Updated tinysort to v3 @peter.toennies
Added link from names in chatbox title to profiles #100 !614 @colomar
## Bugfixes
- Improve/correct user profile badge count !612 @pmayd
## Refactoring
- Removed scrollbars from event view !608 @jofranz
## Dev/Test/CI stuff
- Updated tap-spec in chat to version 5 (fixes vulnerability of lodash) !606 @peter.toennies
- Updated url to 0.11 and tape-spec to version 5 !590 @peter.toennies
- Updated several dev packages: vue eslint parser to v4, eslint plugin vue to v5, css loader to v2 @peter.toennies
- Updated vue-eslint-parser to version 5 and file loader to version 3 !613 @peter.toennies
# 2018-12-24
We are happy to release our next version of the foodsharing homepage today. The most beautiful part of that release is
not its content but the fact that we have input from 15 different developers. The team is growing steadily, which is
really nice.
You will find some new features regarding store pages and food baskets but we have also fixed a big bunch of bugs,
updated and cleaned out a lot of stuff, worked on the interface for our upcoming apps and put some work into the mailing
system of ours. We hope you will enjoy it.
Merry Christmas :-)
## Features
- shows hint in food basket about public information #373 !570 @k.miklobusec
- Fix conversation name when changing store (name) #294 !508 @surrim
......@@ -17,7 +45,8 @@
- Database functions can now be called with critera that contain arrays !559 @janopae
- Added a Rest controller for food baskets #345 !557 @alex.simm
- Allow platform mailing system to work with multiple email domains !583 @NerdyProjects
- Changes MessageRestController limit and offsets to use query parameters
- Changes MessageRestController limit and offsets to use query parameters !587 @theolampert
- Hight adjustments of "next fetches" in store #376 !601 @jofranz
## Bugfixes
- Foodsavers list is now sorted by name and doesn't reshuffle !578 #54 @odedNea
......@@ -27,7 +56,7 @@
- removed not needed add store button from the dashboard !523 @peter.toennies
- limit conversations sent to client at page loading !542 @janopae
- check permissions before saving a wallpost in WallpostXhr !542 @janopae
- stat_fetchrate is calculated correctly and shown in profile #281 @k.miklobusec
- stat_fetchrate is calculated correctly and shown in profile added tvalue in select !598 #281 @k.miklobusec
- fix mail sending by passing instance of Mem to AsyncMail constructor !551 @nicksellen
- fixed wrong html formatting in quick replies to forum posts !534 @peter.toennies
- fixed index check in BasketGateway #354 !556 @alex.simm
......@@ -38,14 +67,14 @@
- Adding pictures to blog posts and Fairteiler work again !581 @NerdyProjects
- Redirect after joining a new region works again !581 @NerdyProjects
- Bell notifications for store fetch confirmations and for new fairteilers are now generated and stored in the database like normal ones #353 !559 @janopae
- Update store bells via new cron command instead on every bell retrieval !610 @NerdyProjects
- More stability for internal email system as emails are handled like external ones now !583 @NerdyProjects
- Fixed safari issue with the navbar !603 @theolampert
## Refactoring
- Unify Symfony DI configuration !544 @nicksellen
- Add comments in scripts for quicker start of new developers !563 @flukx
- Minor refactoring of control flow all over the source !554 and !555 @peter.toennies
- refactored EmailTemplateAdminGateway from model to gateway !482 #9 @peter.toennies
## Dev/Test/CI stuff
......
......@@ -17,21 +17,20 @@
"cookie": "^0.3.1",
"randomstring": "^1.1.5",
"redis": "^2.8.0",
"socket.io": "^2.1.1",
"url": "0.10.1"
"socket.io": "^2.2.0",
"url": "^0.11.0"
},
"devDependencies": {
"browser-env": "<3.2.0",
"eslint": "^5.9.0",
"eslint": "^5.12.0",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^8.0.0",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"request": "^2.81.1",
"socket.io-client": "^2.1.1",
"tap-spec": "^4.1.2",
"tape": "^4.9.1",
"request": "^2.88.0",
"socket.io-client": "^2.2.0",
"tap-spec": "^5.0.0",
"tape": "^4.9.2",
"tape-watch": "^2.3.0"
},
"eslintConfig": {
......
'use strict'
require('browser-env')()
const request = require('request')
const redis = require('redis')
const randomstring = require('randomstring')
const randomString = require('randomstring')
const test = require('tape')
const { spawn } = require('child_process')
const { serialize } = require('cookie')
......@@ -28,8 +27,6 @@ test.onFinish(() => {
server.kill()
})
// Would like to use this one, but extraHeaders seems not to work ok...
// const io = require('../js/socket.io-1.5.0.min.js');
const io = require('socket.io-client')
test('simple connection', t => {
......@@ -141,7 +138,7 @@ test('unregistering', t => {
const socket = connect(t, 'somesessionid')
socket.on('connect', () => {
socket.emit('register')
fetchStats((err, stats) => {
fetchStats((err) => {
socket.disconnect()
t.error(err, 'does not error')
fetchStats((err, stats) => {
......@@ -231,7 +228,7 @@ test('can send and receive a message for multiple clients', t => {
test('can send to php users', t => {
t.timeoutAfter(10000)
t.plan(4)
let sessionId = randomstring.generate()
let sessionId = randomString.generate()
let userId = 1
addPHPSessionToRedis(userId, sessionId, err => {
t.error(err)
......@@ -258,7 +255,7 @@ test('can send to php users', t => {
test('can send to api users', t => {
t.timeoutAfter(10000)
t.plan(4)
let sessionId = randomstring.generate()
let sessionId = randomString.generate()
let userId = 2
addAPISessionToRedis(userId, sessionId, err => {
t.error(err)
......@@ -344,6 +341,7 @@ test('does not send to other users', t => {
function connect (t, sessionId, cookieName = 'PHPSESSID') {
let socket = io.connect(WS_URL, {
transports: ['websocket'],
extraHeaders: {
cookie: serialize(cookieName, sessionId)
}
......@@ -365,11 +363,11 @@ function register (socket, callback) {
}
function sendMessage (params, callback) {
request(HTTP_URL, { qs: params }, (err, response, body) => {
request(HTTP_URL, { qs: params }, (err) => {
if (err) return callback(err)
callback()
})
};
}
function fetchStats (callback) {
request(`${HTTP_URL}/stats`, (err, response, body) => {
......@@ -408,4 +406,4 @@ function assertStats (t, connections, registrations, sessions, callback) {
t.equal(stats.sessions, sessions, 'correct session count')
callback()
})
};
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -12,11 +12,11 @@
"test": "node test"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.5.0",
"@fortawesome/fontawesome-free": "^5.6.3",
"bootstrap-vue": "^2.0.0-rc.11",
"copy-webpack-plugin": "^4.6.0",
"cropperjs": "^1.4.3",
"date-fns": "^1.29.0",
"date-fns": "^1.30.1",
"fullpage.js": "<2.9.6",
"install": "^0.12.2",
"jquery": "<3.0.0-alpha1",
......@@ -26,66 +26,66 @@
"jquery-ui": "<1.12.0-beta.1",
"jquery.ui.position": "^1.11.4",
"leaflet": "<1.0.0-beta.1",
"leaflet.awesome-markers": "^2.0.4",
"leaflet.awesome-markers": "^2.0.5",
"leaflet.markercluster": "<1.0.0-rc.1.0",
"magnific-popup": "^1.1.0",
"node-sass": "^4.10.0",
"node-sass": "^4.11.0",
"object-path": "^0.11.4",
"raven-js": "^3.27.0",
"socket.io-client": "^2.0.0",
"timeago": "^1.4.1",
"tinysort": "^2.3.6",
"socket.io-client": "^2.2.0",
"timeago": "^1.4.3",
"tinysort": "^3.2.5",
"twemoji": "^11.2.0",
"typeahead-addresspicker": "^1.0.1",
"typeface-alfa-slab-one": "^0.0.54",
"underscore": "^1.9.1",
"vue": "^2.5.17",
"vue": "^2.5.21",
"whatwg-fetch": "^3.0.0"
},
"devDependencies": {
"@babel/core": "^7.1.6",
"@babel/preset-env": "^7.1.6",
"@vue/test-utils": "^1.0.0-beta.26",
"@babel/core": "^7.2.2",
"@babel/preset-env": "^7.2.3",
"@vue/test-utils": "^1.0.0-beta.28",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.4",
"css-loader": "^1.0.1",
"dotenv": "^6.1.0",
"eslint": "^5.9.0",
"babel-loader": "^8.0.5",
"css-loader": "^2.1.0",
"dotenv": "^6.2.0",
"eslint": "^5.12.0",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-html": "^5.0.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^8.0.0",
"eslint-plugin-promise": "^4.0.0",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^4.7.1",
"eslint-plugin-vue": "^5.1.0",
"exports-loader": "^0.7.0",
"expose-loader": "^0.7.5",
"file-loader": "^2.0.0",
"file-loader": "^3.0.1",
"glob": "^7.1.3",
"html-webpack-plugin": "^3.0.6",
"html-webpack-plugin": "^3.2.0",
"imports-loader": "^0.8.0",
"jsdom": "^13.0.0",
"jsdom": "^13.1.0",
"jsdom-global": "^3.0.2",
"json-loader": "^0.5.7",
"loader-utils": "^1.1.0",
"mini-css-extract-plugin": "^0.4.5",
"loader-utils": "^1.2.3",
"mini-css-extract-plugin": "^0.5.0",
"mkdirp": "^0.5.1",
"mocha": "^5.2.0",
"node-localstorage": "^1.3.1",
"null-loader": "^0.1.1",
"sass-loader": "^7.1.0",
"shx": "^0.3.2",
"sinon": "^7.1.1",
"sinon": "^7.2.2",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"vue-eslint-parser": "^3.3.0",
"vue-loader": "^15.4.2",
"vue-template-compiler": "^2.5.17",
"webpack": "^4.26.1",
"vue-eslint-parser": "^5.0.0",
"vue-loader": "^15.5.0",
"vue-template-compiler": "^2.5.21",
"webpack": "^4.28.3",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10",
"webpack-merge": "^4.1.4",
"webpack-cli": "^3.2.1",
"webpack-dev-server": "^3.1.14",
"webpack-merge": "^4.2.1",
"yaml-loader": "^0.5.0"
},
"eslintConfig": {
......
......@@ -2,14 +2,17 @@
<form
class="form-inline my-2 my-lg-0"
style="flex-grow: 1"
@submit.prevent>
@submit.prevent
>
<div
ref="inputgroup"
class="input-group mr-2">
class="input-group mr-2"
>
<div class="input-group-prepend">
<label
class="input-group-text text-primary"
for="login-email">
for="login-email"
>
<i class="fas fa-user" />
</label>
</div>
......@@ -26,11 +29,13 @@
</div>
<div
ref="inputgroup"
class="input-group mr-2">
class="input-group mr-2"
>
<div class="input-group-prepend">
<label
class="input-group-text text-primary"
for="login-password">
for="login-password"
>
<i class="fas fa-key" />
</label>
</div>
......@@ -49,14 +54,16 @@
v-if="!isLoading "
href="#"
class="btn btn-secondary btn-sm"
@click="submit">
@click="submit"
>
<i class="fas fa-arrow-right" />
</button>
<button
v-else
class="btn btn-light btn-sm loadingButton"
@click="submit">
<img src="/img/469.gif" >
@click="submit"
>
<img src="/img/469.gif">
</button>
</form>
</template>
......@@ -109,40 +116,42 @@ export default {
</script>
<style lang="scss">
#topbar .input-group {
#topbar .input-group {
margin-bottom: 0;
width: 10em;
@media (max-width: 320px) {
width: 80%;
width: 80%;
}
img, i {
height: 1em;
width: 1em;
height: 1em;
width: 1em;
}
.input-group-text {
background-color: white;
border: none;
padding: 0.1rem 0.4rem;
font-size: .9em;
background-color: white;
border: none;
padding: 0.1rem 0.4rem;
font-size: .9em;
}
input.form-control {
padding: 0.1rem 0.4rem;
font-size: 1em;
padding-left: 0;
font-weight: bold;
font-size: 1em;
padding: 0.1rem 0.4rem 0.1rem 0;
font-weight: bold;
border: none;
&:focus {
box-shadow: none;
border: none;
&:focus {
box-shadow: none;
border: none;
}
}
}
}
}
.loadingButton {
.loadingButton {
img {
height: 1em;
height: 1em;
}
}
}
</style>
......@@ -2,16 +2,20 @@
<nav-item-dropdown
tooltip="Administration"
right
no-caret>
no-caret
>
<template slot="button-content">
<i class="fas fa-cog"/>
<span class="d-md-none">Administration</span>
<i class="fas fa-cog" />
<span class="d-md-none">
Administration
</span>
</template>
<a
v-for="item in items"
:key="item.url"
:href="item.url"
class="dropdown-item">
class="dropdown-item"
>
<i :class="item.icon" /> {{ item.label }}
</a>
</nav-item-dropdown>
......
......@@ -3,20 +3,25 @@
ref="dropdown"
:no-caret="!showLabel"
tooltip="Essenskörbe"
class="topbar-baskets">
class="topbar-baskets"
>
<template slot="button-content">
<i class="fas fa-shopping-basket"/>
<span v-if="showLabel">Essenskörbe</span>
<i class="fas fa-shopping-basket" />
<span v-if="showLabel">
Essenskörbe
</span>
</template>
<div class="list-group">
<p
v-if="!baskets.length"
class="dropdown-header">
class="dropdown-header"
>
Du hast keine Essenskörbe eingetragen
</p>
<div
v-else
class="scroll-container">
class="scroll-container"
>
<menu-baskets-entry
v-for="basket in basketsSorted"
:key="basket.id"
......@@ -27,13 +32,15 @@
<div class="list-grou-item p-2 text-center">
<a
:href="$url('baskets')"
class="btn btn-sm btn-secondary">
class="btn btn-sm btn-secondary"
>
Alle Essenskörbe
</a>
<a
href="#"
class="btn btn-sm btn-secondary"
@click="openBasketCreationForm">
@click="openBasketCreationForm"
>
Essenskorb anlegen
</a>
</div>
......
<template>
<a
:href="$url('basket', basket.id)"
class="list-group-item list-group-item-action">
class="list-group-item list-group-item-action"
>
<div class="row">
<div class="col-2 pl-2">
<img src="/img/basket.png" >
<img src="/img/basket.png">
</div>
<div class="col-10">
<div class="text-truncate"><b>{{ basket.description }}</b></div>
<div class="text-truncate">
<b>{{ basket.description }}</b>
</div>
<small
v-if="!basket.requests.length"
class="text-muted">
class="text-muted"
>
Bisher keine Anfragen erhalten
</small>
<h5
v-if="basket.requests.length"
class="text-muted mb-1 pl-2">angefragt von</h5>
class="text-muted mb-1 pl-2"
>
angefragt von
</h5>
<div
v-if="basket.requests.length"
class="requests list-group">
class="requests list-group"
>
<a
v-for="req in basket.requests"
:key="req.time"
href="#"
class="list-group-item list-group-item-action p-1 request"
@click.prevent="openChat(req.user.id, $event)">
@click.prevent="openChat(req.user.id, $event)"
>
<div class="row pl-1 align-items-center">
<div class="col-1 text-right pt-1">
<avatar
......@@ -35,7 +44,9 @@
</div>
<div class="col-10 pt-1">
<div class="row">
<h6 class="col text-truncate mb-1">{{ req.user.name }}</h6>
<h6 class="col text-truncate mb-1">
{{ req.user.name }}
</h6>
<div class="col nowrap text-right text-muted nhover">
{{ req.time | dateDistanceInWords }}
</div>
......@@ -45,9 +56,11 @@
href="#"
class="m-1 btn btn-sm btn-secondary"
title="Essensanfrage abschließen"
@click.prevent.stop="openRemoveDialog(req.user.id, $event)"><i class="fas fa-times" /></a>
@click.prevent.stop="openRemoveDialog(req.user.id, $event)"
>
<i class="fas fa-times" />
</a>
</div>
</div>
</div>
</div>
......@@ -99,7 +112,7 @@ h5 {
}
.request .btn {
padding: 0rem 0.2rem;
padding: 0 0.2rem;
position: absolute;
right: 1.2em;
top: -0.3em;
......
......@@ -3,17 +3,24 @@
tooltip="Benachrichtigungen"
no-caret
right
class="topbar-bells">
class="topbar-bells"
>
<template slot="button-content">
<i class="fas fa-bell"/>
<i class="fas fa-bell" />
<span
v-if="unread"
class="badge badge-danger">{{ unread }}</span>
class="badge badge-danger"
>
{{ unread }}
</span>
</template>
<div class="list-group">
<small
v-if="!bells.length"
class="list-group-item text-muted">Du hast derzeit keine Benachrichtigungen</small>
class="list-group-item text-muted"
>
Du hast derzeit keine Benachrichtigungen
</small>
<menu-bells-entry
v-for="bell in bells"
:key="bell.id"
......
......@@ -6,27 +6,48 @@
>
<div class="row">
<div class="col-2 icon-side">
<i
v-if="bell.icon"
:class="[
`icon ${bell.icon}`,
bell.isCloseable ? 'hideonhover' : ''
]"
/>
<div
v-if="bell.image"
:class="[
'icon',
bell.isCloseable ? 'hideonhover' : ''
]"
>
<img :src="bell.image">
</div>
<a
v-if="bell.isCloseable"
class="showonhover"
href="#"
@click.stop="$emit('remove', bell.id)">
@click.stop="$emit('remove', bell.id)"
>
<i
v-if="bell.icon"
:class="`icon ${bell.icon}`" />
<div
v-if="bell.image"
class="icon"><img :src="bell.image" ></div>
<i class="fas fa-times" />
<!-- <div :class="['avatar', 'avatar_'+avatars.length]">
<div v-for="avatar in avatars" :key="avatar" :style="{backgroundImage: `url('${avatar}')`}" />
</div> -->
class="fas fa-times"
/>
</a>
<!-- <div :class="['avatar', 'avatar_'+avatars.length]">
<div v-for="avatar in avatars" :key="avatar" :style="{backgroundImage: `url('${avatar}')`}" />
</div> -->
</div>
<div class="col-10">
<div class="mt-1 d-flex w-100 justify-content-between">
<h5 class="mb-1">{{ $i18n(`bell.${bell.key}_title`, bell.payload) }}</h5>
<small class="text-muted text-right nowrap">{{ bell.createdAt | dateDistanceInWords }}</small>
<h5 class="mb-1">
{{ $i18n(`bell.${bell.key}_title`, bell.payload) }}
</h5>
<small class="text-muted text-right nowrap">
{{ bell.createdAt | dateDistanceInWords }}
</small>
</div>
<p class="mb-1 text-truncate">{{ $i18n(`bell.${bell.key}`, bell.payload) }}</p>
<p class="mb-1 text-truncate">
{{ $i18n(`bell.${bell.key}`, bell.payload) }}
</p>
</div>
</div>
</a>
......@@ -58,57 +79,62 @@ export default {
</script>
<style lang="scss" scoped>
h5 {
h5 {
font-weight: bold;
font-size: 0.9em;
}
p {
}
p {