Merge branch 'release/0.0.13'
This commit is contained in:
commit
aa0316ffe0
42 changed files with 273 additions and 547 deletions
|
|
@ -204,34 +204,37 @@ class MicropubClientController extends Controller
|
|||
*/
|
||||
public function postNewPlace(Request $request)
|
||||
{
|
||||
if ($request->session()->has('token') === false) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'error_description' => 'No known token',
|
||||
], 400);
|
||||
}
|
||||
$domain = $request->session()->get('me');
|
||||
$token = $request->session()->get('token');
|
||||
|
||||
$micropubEndpoint = $this->indieAuthService->discoverMicropubEndpoint($domain, $this->indieClient);
|
||||
if (! $micropubEndpoint) {
|
||||
return (new Response(json_encode([
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => 'Could not determine the micropub endpoint.',
|
||||
]), 400))
|
||||
->header('Content-Type', 'application/json');
|
||||
'error_description' => 'Could not determine the micropub endpoint.',
|
||||
], 400);
|
||||
}
|
||||
|
||||
$place = $this->postPlaceRequest($request, $micropubEndpoint, $token);
|
||||
if ($place === false) {
|
||||
return (new Response(json_encode([
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => 'Unable to create the new place',
|
||||
]), 400))
|
||||
->header('Content-Type', 'application/json');
|
||||
'error_description' => 'Unable to create the new place',
|
||||
], 400);
|
||||
}
|
||||
|
||||
return (new Response(json_encode([
|
||||
return response()->json([
|
||||
'url' => $place,
|
||||
'name' => $request->input('place-name'),
|
||||
'latitude' => $request->input('place-latitude'),
|
||||
'longitude' => $request->input('place-longitude'),
|
||||
]), 200))
|
||||
->header('Content-Type', 'application/json');
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -263,7 +266,7 @@ class MicropubClientController extends Controller
|
|||
'headers' => $headers,
|
||||
]);
|
||||
} catch (ClientException $e) {
|
||||
//not sure yet...
|
||||
return false;
|
||||
}
|
||||
if ($response->getStatusCode() == 201) {
|
||||
return $response->getHeader('Location')[0];
|
||||
|
|
@ -285,12 +288,22 @@ class MicropubClientController extends Controller
|
|||
$latitude,
|
||||
$longitude
|
||||
) {
|
||||
if ($request->session()->has('token') === false) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'error_description' => 'No known token',
|
||||
], 400);
|
||||
}
|
||||
$domain = $request->session()->get('me');
|
||||
$token = $request->session()->get('token');
|
||||
|
||||
$micropubEndpoint = $this->indieAuthService->discoverMicropubEndpoint($domain, $this->indieClient);
|
||||
|
||||
if (! $micropubEndpoint) {
|
||||
return;
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'error_description' => 'No known endpoint',
|
||||
], 400);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -299,7 +312,10 @@ class MicropubClientController extends Controller
|
|||
'query' => ['q' => 'geo:' . $latitude . ',' . $longitude],
|
||||
]);
|
||||
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
|
||||
return;
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'error_description' => 'The endpoint returned a non-good response',
|
||||
], 400);
|
||||
}
|
||||
|
||||
return (new Response($response->getBody(), 200))
|
||||
|
|
|
|||
|
|
@ -57,54 +57,44 @@ class MicropubController extends Controller
|
|||
if (array_search('post', $scopes) !== false) {
|
||||
$clientId = $tokenData->getClaim('client_id');
|
||||
if (($request->input('h') == 'entry') || ($request->input('type')[0] == 'h-entry')) {
|
||||
$note = $this->noteService->createNote($request, $clientId);
|
||||
$content = <<<EOD
|
||||
{
|
||||
"response": "created",
|
||||
"location": "$note->longurl"
|
||||
}
|
||||
EOD;
|
||||
try {
|
||||
$note = $this->noteService->createNote($request, $clientId);
|
||||
} catch (Exception $exception) {
|
||||
return response()->json(['error' => true], 400);
|
||||
}
|
||||
|
||||
return (new Response($content, 201))
|
||||
->header('Location', $note->longurl)
|
||||
->header('Content-Type', 'application/json');
|
||||
return response()->json([
|
||||
'response' => 'created',
|
||||
'location' => $note->longurl,
|
||||
], 201)->header('Location', $note->longurl);
|
||||
}
|
||||
if ($request->input('h') == 'card' || $request->input('type')[0] == 'h-card') {
|
||||
$place = $this->placeService->createPlace($request);
|
||||
$content = <<<EOD
|
||||
{
|
||||
"response": "created",
|
||||
"location": "$place->longurl"
|
||||
}
|
||||
EOD;
|
||||
try {
|
||||
$place = $this->placeService->createPlace($request);
|
||||
} catch (Exception $exception) {
|
||||
return response()->json(['error' => true], 400);
|
||||
}
|
||||
|
||||
return (new Response($content, 201))
|
||||
->header('Location', $place->longurl)
|
||||
->header('Content-Type', 'application/json');
|
||||
return response()->json([
|
||||
'response' => 'created',
|
||||
'location' => $place->longurl,
|
||||
], 201)->header('Location', $place->longurl);
|
||||
}
|
||||
}
|
||||
}
|
||||
$content = <<<'EOD'
|
||||
{
|
||||
"response": "error",
|
||||
"error": "invalid_token",
|
||||
"error_description": "The token provided is not valid or does not have the necessary scope",
|
||||
}
|
||||
EOD;
|
||||
|
||||
return (new Response($content, 400))
|
||||
->header('Content-Type', 'application/json');
|
||||
return response()->json([
|
||||
'response' => 'error',
|
||||
'error' => 'invalid_token',
|
||||
'error_description' => 'The token provided is not valid or does not have the necessary scope',
|
||||
], 400);
|
||||
}
|
||||
$content = <<<'EOD'
|
||||
{
|
||||
"response": "error",
|
||||
"error": "no_token",
|
||||
"error_description": "No OAuth token sent with request"
|
||||
}
|
||||
EOD;
|
||||
|
||||
return (new Response($content, 400))
|
||||
->header('Content-Type', 'application/json');
|
||||
return response()->json([
|
||||
'response' => 'error',
|
||||
'error' => 'no_token',
|
||||
'error_description' => 'No OAuth token sent with request',
|
||||
], 400);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@ namespace App;
|
|||
|
||||
use DB;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Phaza\LaravelPostgis\Geometries\Point;
|
||||
use MartinBean\Database\Eloquent\Sluggable;
|
||||
use Phaza\LaravelPostgis\Geometries\Polygon;
|
||||
use Phaza\LaravelPostgis\Eloquent\PostgisTrait;
|
||||
|
||||
class Place extends Model
|
||||
|
|
@ -33,8 +31,8 @@ class Place extends Model
|
|||
* @var array
|
||||
*/
|
||||
protected $postgisFields = [
|
||||
'location' => Point::class,
|
||||
'polygon' => Polygon::class,
|
||||
'location',
|
||||
'polygon',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -16,21 +16,26 @@ class PlaceService
|
|||
*/
|
||||
public function createPlace(Request $request)
|
||||
{
|
||||
//we’ll either have latitude and longitude sent together in a
|
||||
//geo-url (micropub), or seperatley (/admin)
|
||||
if ($request->input('geo') !== null) {
|
||||
$parts = explode(':', $request->input('geo'));
|
||||
$latlng = explode(',', $parts[1]);
|
||||
$latitude = $latlng[0];
|
||||
$longitude = $latlng[1];
|
||||
if ($request->header('Content-Type') == 'application/json') {
|
||||
$name = $request->input('properties.name');
|
||||
$description = $request->input('properties.description') ?? null;
|
||||
$geo = $request->input('properties.geo');
|
||||
} else {
|
||||
$name = $request->input('name');
|
||||
$description = $request->input('description');
|
||||
$geo = $request->input('geo');
|
||||
}
|
||||
$parts = explode(':', $geo);
|
||||
$latlng = explode(',', $parts[1]);
|
||||
$latitude = $latlng[0];
|
||||
$longitude = $latlng[1];
|
||||
if ($request->input('latitude') !== null) {
|
||||
$latitude = $request->input('latitude');
|
||||
$longitude = $request->input('longitude');
|
||||
}
|
||||
$place = new Place();
|
||||
$place->name = $request->input('name');
|
||||
$place->description = $request->input('description');
|
||||
$place->name = $name;
|
||||
$place->description = $description;
|
||||
$place->location = new Point((float) $latitude, (float) $longitude);
|
||||
$place->save();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
# Changelog
|
||||
|
||||
## Version 0.0.13 (2016-09-26)
|
||||
- Better places support, particularly with micropub (issue#9)
|
||||
- Uglify js for better performance (issue#19)
|
||||
- Autolink spotify links (issue#18)
|
||||
|
||||
## Version 0.0.12 (2016-09-21)
|
||||
- Better indication of number of replies to a note (issue#17)
|
||||
- Use generic twitter status URL so my own profile name isn’t hardcoded (issue#14)
|
||||
|
|
|
|||
51
composer.lock
generated
51
composer.lock
generated
|
|
@ -58,16 +58,16 @@
|
|||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.19.9",
|
||||
"version": "3.19.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "55da42fee5ff26f962b2366b08e4f32e348cd1d9"
|
||||
"reference": "eb9488f671175e708cf68c74cc04bd9115c96761"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/55da42fee5ff26f962b2366b08e4f32e348cd1d9",
|
||||
"reference": "55da42fee5ff26f962b2366b08e4f32e348cd1d9",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/eb9488f671175e708cf68c74cc04bd9115c96761",
|
||||
"reference": "eb9488f671175e708cf68c74cc04bd9115c96761",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -134,7 +134,7 @@
|
|||
"s3",
|
||||
"sdk"
|
||||
],
|
||||
"time": "2016-09-20 22:11:12"
|
||||
"time": "2016-09-22 19:32:03"
|
||||
},
|
||||
{
|
||||
"name": "barnabywalters/mf-cleaner",
|
||||
|
|
@ -2891,16 +2891,16 @@
|
|||
},
|
||||
{
|
||||
"name": "spatie/laravel-medialibrary",
|
||||
"version": "4.8.4",
|
||||
"version": "4.9.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/laravel-medialibrary.git",
|
||||
"reference": "8c862e270d49e8bbff6f0993900c8bb59ea165ea"
|
||||
"reference": "bb8786724f87c2d187897809849b7dc79a84a4d9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/8c862e270d49e8bbff6f0993900c8bb59ea165ea",
|
||||
"reference": "8c862e270d49e8bbff6f0993900c8bb59ea165ea",
|
||||
"url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/bb8786724f87c2d187897809849b7dc79a84a4d9",
|
||||
"reference": "bb8786724f87c2d187897809849b7dc79a84a4d9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -2910,7 +2910,7 @@
|
|||
"illuminate/support": "~5.1.16|~5.2.0|~5.3.0",
|
||||
"php": "^7.0",
|
||||
"spatie/laravel-glide": "^3.0.0",
|
||||
"spatie/pdf-to-image": "^1.0.1",
|
||||
"spatie/pdf-to-image": "^1.2",
|
||||
"spatie/string": "^2.0.0"
|
||||
},
|
||||
"conflict": {
|
||||
|
|
@ -2919,8 +2919,7 @@
|
|||
"require-dev": {
|
||||
"doctrine/dbal": "^2.5.2",
|
||||
"mockery/mockery": "^0.9.4",
|
||||
"orchestra/database": "3.3.x-dev",
|
||||
"orchestra/testbench": "3.3.x-dev",
|
||||
"orchestra/testbench": "^3.1",
|
||||
"phpunit/phpunit": "^5.0.0",
|
||||
"scrutinizer/ocular": "^1.1"
|
||||
},
|
||||
|
|
@ -2954,7 +2953,7 @@
|
|||
"media",
|
||||
"spatie"
|
||||
],
|
||||
"time": "2016-09-14 16:31:49"
|
||||
"time": "2016-09-23 11:54:31"
|
||||
},
|
||||
{
|
||||
"name": "spatie/pdf-to-image",
|
||||
|
|
@ -4031,28 +4030,28 @@
|
|||
"packages-dev": [
|
||||
{
|
||||
"name": "barryvdh/laravel-debugbar",
|
||||
"version": "V2.2.3",
|
||||
"version": "v2.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/barryvdh/laravel-debugbar.git",
|
||||
"reference": "ecd1ce5c4a827e2f6a8fb41bcf67713beb1c1cbd"
|
||||
"reference": "0c87981df959c7c1943abe227baf607c92f204f9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/ecd1ce5c4a827e2f6a8fb41bcf67713beb1c1cbd",
|
||||
"reference": "ecd1ce5c4a827e2f6a8fb41bcf67713beb1c1cbd",
|
||||
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/0c87981df959c7c1943abe227baf607c92f204f9",
|
||||
"reference": "0c87981df959c7c1943abe227baf607c92f204f9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "5.1.*|5.2.*|5.3.*",
|
||||
"maximebf/debugbar": "~1.11.0|~1.12.0",
|
||||
"maximebf/debugbar": "~1.13.0",
|
||||
"php": ">=5.5.9",
|
||||
"symfony/finder": "~2.7|~3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.2-dev"
|
||||
"dev-master": "2.3-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
|
@ -4081,7 +4080,7 @@
|
|||
"profiler",
|
||||
"webprofiler"
|
||||
],
|
||||
"time": "2016-07-29 15:00:36"
|
||||
"time": "2016-09-15 14:05:56"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
|
|
@ -4232,16 +4231,16 @@
|
|||
},
|
||||
{
|
||||
"name": "maximebf/debugbar",
|
||||
"version": "v1.12.0",
|
||||
"version": "v1.13.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maximebf/php-debugbar.git",
|
||||
"reference": "e634fbd32cd6bc3fa0e8c972b52d4bf49bab3988"
|
||||
"reference": "5f49a5ed6cfde81d31d89378806670d77462526e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/e634fbd32cd6bc3fa0e8c972b52d4bf49bab3988",
|
||||
"reference": "e634fbd32cd6bc3fa0e8c972b52d4bf49bab3988",
|
||||
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/5f49a5ed6cfde81d31d89378806670d77462526e",
|
||||
"reference": "5f49a5ed6cfde81d31d89378806670d77462526e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -4260,7 +4259,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.12-dev"
|
||||
"dev-master": "1.13-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
|
@ -4289,7 +4288,7 @@
|
|||
"debug",
|
||||
"debugbar"
|
||||
],
|
||||
"time": "2016-05-15 13:11:34"
|
||||
"time": "2016-09-15 14:01:59"
|
||||
},
|
||||
{
|
||||
"name": "mockery/mockery",
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ return [
|
|||
'Artisan' => Illuminate\Support\Facades\Artisan::class,
|
||||
'Auth' => Illuminate\Support\Facades\Auth::class,
|
||||
'Blade' => Illuminate\Support\Facades\Blade::class,
|
||||
'Bus' => Illuminate\Support\Facades\Bus::class,
|
||||
'Cache' => Illuminate\Support\Facades\Cache::class,
|
||||
'Config' => Illuminate\Support\Facades\Config::class,
|
||||
'Cookie' => Illuminate\Support\Facades\Cookie::class,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
var gulp = require('gulp');
|
||||
var pump = require('pump');
|
||||
var sass = require('gulp-sass');
|
||||
var brotli = require('gulp-brotli');
|
||||
var uglify = require('gulp-uglify');
|
||||
var zopfli = require('gulp-zopfli');
|
||||
var sourcemaps = require('gulp-sourcemaps');
|
||||
var autoprefixer = require('gulp-autoprefixer');
|
||||
|
|
@ -17,7 +19,12 @@ gulp.task('sass', function () {
|
|||
});
|
||||
|
||||
gulp.task('js-assets', function () {
|
||||
//return gulp.src(['resources/assets/js/**/*'])
|
||||
// .pipe(gulp.dest('./public/assets/js'));
|
||||
return gulp.src(['resources/assets/js/**/*'])
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(uglify())
|
||||
.pipe(sourcemaps.write('./maps'))
|
||||
.pipe(gulp.dest('./public/assets/js'));
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
"gulp-brotli": "^1.0.1",
|
||||
"gulp-sass": "^2.3.2",
|
||||
"gulp-sourcemaps": "^1.6.0",
|
||||
"gulp-uglify": "^2.0.0",
|
||||
"gulp-zopfli": "^1.0.0",
|
||||
"lint-staged": "^1.0.1",
|
||||
"pre-commit": "^1.1.3",
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,69 +1,2 @@
|
|||
/* global alertify, store */
|
||||
var feature = {
|
||||
addEventListener : !!window.addEventListener,
|
||||
querySelectorAll : !!document.querySelectorAll
|
||||
};
|
||||
|
||||
if (feature.addEventListener && feature.querySelectorAll) {
|
||||
var keys = getKeys();
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
if (store.get(keys[i])) {
|
||||
var formId = keys[i].split('~')[1];
|
||||
document.getElementById(formId).value = store.get(keys[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var timerId = window.setInterval(function() {
|
||||
var saved = false;
|
||||
var inputs = document.querySelectorAll('input[type=text], textarea');
|
||||
for (var i = 0; i < inputs.length; i++) {
|
||||
var key = getFormElement(inputs[i]).id + '~' + inputs[i].id;
|
||||
if (store.get(key) !== inputs[i].value && inputs[i].value !== '') {
|
||||
store.set(key, inputs[i].value);
|
||||
saved = true;
|
||||
}
|
||||
}
|
||||
if (saved === true) {
|
||||
alertify.logPosition('top right');
|
||||
alertify.success('Auto saved text');
|
||||
}
|
||||
}, 5000);
|
||||
var forms = document.querySelectorAll('form');
|
||||
for (var f = 0; f < forms.length; f++) {
|
||||
var form = forms[f];
|
||||
form.addEventListener('submit', function() {
|
||||
window.clearInterval(timerId);
|
||||
var formId = form.id;
|
||||
var storedKeys = store.keys();
|
||||
for (var i = 0; i < storedKeys.length; i++) {
|
||||
if (storedKeys[i].indexOf(formId) > -1) {
|
||||
store.remove(storedKeys[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function getKeys() {
|
||||
var keys = [];
|
||||
var formFields = document.querySelectorAll('input[type=text], textarea');
|
||||
for (var f = 0; f < formFields.length; f++) {
|
||||
var parent = getFormElement(formFields[f]);
|
||||
if (parent !== false) {
|
||||
var key = parent.id + '~' + formFields[f].id;
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
function getFormElement(elem) {
|
||||
if (elem.nodeName.toLowerCase() !== 'body') {
|
||||
var parent = elem.parentNode;
|
||||
if (parent.nodeName.toLowerCase() === 'form') {
|
||||
return parent;
|
||||
} else {
|
||||
return getFormElement(parent);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function getKeys(){for(var e=[],t=document.querySelectorAll("input[type=text], textarea"),r=0;r<t.length;r++){var o=getFormElement(t[r]);if(o!==!1){var n=o.id+"~"+t[r].id;e.push(n)}}return e}function getFormElement(e){if("body"!==e.nodeName.toLowerCase()){var t=e.parentNode;return"form"===t.nodeName.toLowerCase()?t:getFormElement(t)}return!1}var feature={addEventListener:!!window.addEventListener,querySelectorAll:!!document.querySelectorAll};if(feature.addEventListener&&feature.querySelectorAll)for(var keys=getKeys(),i=0;i<keys.length;i++)if(store.get(keys[i])){var formId=keys[i].split("~")[1];document.getElementById(formId).value=store.get(keys[i])}for(var timerId=window.setInterval(function(){for(var e=!1,t=document.querySelectorAll("input[type=text], textarea"),r=0;r<t.length;r++){var o=getFormElement(t[r]).id+"~"+t[r].id;store.get(o)!==t[r].value&&""!==t[r].value&&(store.set(o,t[r].value),e=!0)}e===!0&&(alertify.logPosition("top right"),alertify.success("Auto saved text"))},5e3),forms=document.querySelectorAll("form"),f=0;f<forms.length;f++){var form=forms[f];form.addEventListener("submit",function(){window.clearInterval(timerId);for(var e=form.id,t=store.keys(),r=0;r<t.length;r++)t[r].indexOf(e)>-1&&store.remove(t[r])})}
|
||||
//# sourceMappingURL=maps/form-save.js.map
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue