オカズリンクの一次対応

This commit is contained in:
shibafu 2018-01-05 00:26:48 +09:00
parent 2fe3d7ac49
commit b562b3b400
9 changed files with 147 additions and 47 deletions

View File

@ -10,7 +10,7 @@ class Ejaculation extends Model
protected $fillable = [
'user_id', 'ejaculated_date',
'note', 'geo_latitude', 'geo_longitude',
'note', 'geo_latitude', 'geo_longitude', 'link',
'is_private'
];

View File

@ -27,6 +27,7 @@ class EjaculationController extends Controller
'date' => 'required|date_format:Y/m/d',
'time' => 'required|date_format:H:i',
'note' => 'nullable|string|max:500',
'link' => 'nullable|url',
])->after(function ($validator) use ($request, $inputs) {
// 日時の重複チェック
if (!$validator->errors()->hasAny(['date', 'time'])) {
@ -41,6 +42,7 @@ class EjaculationController extends Controller
'user_id' => Auth::id(),
'ejaculated_date' => Carbon::createFromFormat('Y/m/d H:i', $inputs['date'] . ' ' . $inputs['time']),
'note' => $inputs['note'] ?? '',
'link' => $inputs['link'] ?? '',
'is_private' => $request->has('is_private') ?? false
]);
@ -88,6 +90,7 @@ class EjaculationController extends Controller
'date' => 'required|date_format:Y/m/d',
'time' => 'required|date_format:H:i',
'note' => 'nullable|string|max:500',
'link' => 'nullable|url',
])->after(function ($validator) use ($id, $request, $inputs) {
// 日時の重複チェック
if (!$validator->errors()->hasAny(['date', 'time'])) {
@ -101,6 +104,7 @@ class EjaculationController extends Controller
$ejaculation->fill([
'ejaculated_date' => Carbon::createFromFormat('Y/m/d H:i', $inputs['date'] . ' ' . $inputs['time']),
'note' => $inputs['note'] ?? '',
'link' => $inputs['link'] ?? '',
'is_private' => $request->has('is_private') ?? false
])->save();

View File

@ -26,6 +26,7 @@ id,
ejaculated_date,
note,
is_private,
link,
to_char(lead(ejaculated_date, 1, NULL) OVER (ORDER BY ejaculated_date DESC), 'YYYY/MM/DD HH24:MI') AS before_date,
to_char(ejaculated_date - (lead(ejaculated_date, 1, NULL) OVER (ORDER BY ejaculated_date DESC)), 'FMDDD日 FMHH24時間 FMMI分') AS ejaculated_span
SQL

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddLinkToEjaculations extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('ejaculations', function (Blueprint $table) {
$table->string('link')->default('');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('ejaculations', function (Blueprint $table) {
$table->removeColumn('link');
});
}
}

View File

@ -44,32 +44,19 @@
</small>
</div>
</div>
--}}
<div class="form-row">
<div class="form-group col-sm-12">
<label for="link"><span class="oi oi-link-intact"></span> オカズリンク</label>
<input id="link" type="text" class="form-control" placeholder="https://...">
<input id="link" name="link" type="text" class="form-control {{ $errors->has('link') ? ' is-invalid' : '' }}" placeholder="http://..." value="{{ old('link') }}">
<small class="form-text text-muted">
オカズのURLを貼り付けて登録することができます。
</small>
</div>
<div class="form-group col-sm-12 d-none">
<div class="card">
<div class="card-header">このオカズで合っていますか?</div>
<div class="card-body">
<div class="d-flex mb-4">
<img src="holder.js/128x128" alt="" class="rounded">
<div class="align-self-center ml-2 mr-auto">
<p class="mb-1">タイトル</p>
<small class="text-muted">概要</small>
</div>
</div>
<a href="#" class="btn btn-success"><span class="oi oi-check"></span> 決定</a>
<a href="#" class="btn btn-outline-secondary">キャンセル</a>
</div>
</div>
@if ($errors->has('link'))
<div class="invalid-feedback">{{ $errors->first('link') }}</div>
@endif
</div>
</div>
--}}
<div class="form-row">
<div class="form-group col-sm-12">
<label for="note"><span class="oi oi-comment-square"></span> ノート</label>

View File

@ -45,32 +45,19 @@
</small>
</div>
</div>
--}}
<div class="form-row">
<div class="form-group col-sm-12">
<label for="link"><span class="oi oi-link-intact"></span> オカズリンク</label>
<input id="link" type="text" class="form-control" placeholder="https://...">
<input id="link" name="link" type="text" class="form-control {{ $errors->has('link') ? ' is-invalid' : '' }}" placeholder="http://..." value="{{ old('link') ?? $ejaculation->link }}">
<small class="form-text text-muted">
オカズのURLを貼り付けて登録することができます。
</small>
</div>
<div class="form-group col-sm-12 d-none">
<div class="card">
<div class="card-header">このオカズで合っていますか?</div>
<div class="card-body">
<div class="d-flex mb-4">
<img src="holder.js/128x128" alt="" class="rounded">
<div class="align-self-center ml-2 mr-auto">
<p class="mb-1">タイトル</p>
<small class="text-muted">概要</small>
</div>
</div>
<a href="#" class="btn btn-success"><span class="oi oi-check"></span> 決定</a>
<a href="#" class="btn btn-outline-secondary">キャンセル</a>
</div>
</div>
@if ($errors->has('link'))
<div class="invalid-feedback">{{ $errors->first('link') }}</div>
@endif
</div>
</div>
--}}
<div class="form-row">
<div class="form-group col-sm-12">
<label for="note"><span class="oi oi-comment-square"></span> ノート</label>

View File

@ -46,17 +46,20 @@
</p>
@endif
<!-- okazu link -->
{{--
<div class="card mb-2 w-50" style="font-size: small;">
<a class="text-dark card-link" href="#">
<img src="holder.js/320x240" alt="Thumbnail" class="card-img-top">
@if (!empty($ejaculation->link))
<div id="linkCard" class="card mb-2 w-50 d-none" style="font-size: small;">
<a class="text-dark card-link" href="{{ $ejaculation->link }}">
<img src="" alt="Thumbnail" class="card-img-top bg-secondary">
<div class="card-body">
<h6 class="card-title">タイトル</h6>
<p class="card-text">コンテンツの説明文</p>
</div>
</a>
</div>
--}}
<p class="mb-2">
<span class="oi oi-link-intact mr-1"></span><a href="{{ $ejaculation->link }}">{{ $ejaculation->link }}</a>
</p>
@endif
<!-- note -->
@if (!empty($ejaculation->note))
<p class="mb-0 tis-word-wrap">
@ -87,6 +90,7 @@
@endsection
@push('script')
<script type="text/javascript" src="//cdn.jsdelivr.net/npm/holderjs@2.9.4/holder.min.js"></script>
<script>
$('#deleteCheckinModal').on('show.bs.modal', function (event) {
var target = $(event.relatedTarget);
@ -99,5 +103,22 @@
form.attr('action', form.attr('action').replace('@', modal.data('id')));
form.submit();
});
var $linkCard = $('#linkCard');
if ($linkCard.length > 0) {
$.ajax({
url: '{{ url('/api/ogp') }}',
method: 'get',
type: 'json',
data: {
url: $linkCard.find('a').attr('href')
}
}).then(function (data) {
$linkCard.find('.card-title').text(data.title);
$linkCard.find('.card-text').text(data.description);
$linkCard.find('img').attr('src', data.image);
$linkCard.removeClass('d-none');
});
}
</script>
@endpush

View File

@ -32,17 +32,20 @@
</p>
@endif
<!-- okazu link -->
{{--
<div class="card mb-2 w-50" style="font-size: small;">
<a class="text-dark card-link" href="#">
<img src="holder.js/320x240" alt="Thumbnail" class="card-img-top">
@if (!empty($ejaculation->link))
<div class="card link-card mb-2 w-50 d-none" style="font-size: small;">
<a class="text-dark card-link" href="{{ $ejaculation->link }}">
<img src="" alt="Thumbnail" class="card-img-top bg-secondary">
<div class="card-body">
<h6 class="card-title">タイトル</h6>
<p class="card-text">コンテンツの説明文</p>
</div>
</a>
</div>
--}}
<p class="mb-2">
<span class="oi oi-link-intact mr-1"></span><a href="{{ $ejaculation->link }}">{{ $ejaculation->link }}</a>
</p>
@endif
<!-- note -->
@if (!empty($ejaculation->note))
<p class="mb-0 tis-word-wrap">
@ -104,5 +107,22 @@
form.attr('action', form.attr('action').replace('@', modal.data('id')));
form.submit();
});
$('.link-card').each(function () {
var $this = $(this);
$.ajax({
url: '{{ url('/api/ogp') }}',
method: 'get',
type: 'json',
data: {
url: $this.find('a').attr('href')
}
}).then(function (data) {
$this.find('.card-title').text(data.title);
$this.find('.card-text').text(data.description);
$this.find('img').attr('src', data.image);
$this.removeClass('d-none');
});
});
</script>
@endpush

View File

@ -16,3 +16,51 @@ use Illuminate\Http\Request;
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::get('/ogp', function (Request $request) {
$request->validate([
'url:required|url'
]);
$client = new GuzzleHttp\Client();
$res = $client->get($request->input('url'));
if ($res->getStatusCode() === 200) {
$dom = new DOMDocument();
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
$xpath = new DOMXPath($dom);
$result = [
'title' => '',
'description' => '',
'image' => ''
];
$titleNode = $xpath->query('//meta[@*="og:title"]');
foreach ($titleNode as $node) {
if (!empty($node->getAttribute('content'))) {
$result['title'] = $node->getAttribute('content');
break;
}
}
$descriptionNode = $xpath->query('//meta[@*="og:description"]');
foreach ($descriptionNode as $node) {
if (!empty($node->getAttribute('content'))) {
$result['description'] = $node->getAttribute('content');
break;
}
}
$imageNode = $xpath->query('//meta[@*="og:image"]');
foreach ($imageNode as $node) {
if (!empty($node->getAttribute('content'))) {
$result['image'] = $node->getAttribute('content');
break;
}
}
return response()->json($result);
} else {
abort($res->getStatusCode());
}
});