Merge branch 'develop' into feature/300-incoming-webhook
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import * as Cookies from 'js-cookie';
|
||||
import jqXHR = JQuery.jqXHR;
|
||||
import { fetchPostJson, fetchDeleteJson, ResponseError } from './fetch';
|
||||
|
||||
require('./bootstrap');
|
||||
|
||||
@@ -41,57 +41,46 @@ $(() => {
|
||||
const isLiked = $this.data('liked');
|
||||
|
||||
if (isLiked) {
|
||||
const callback = (data: any) => {
|
||||
$this.data('liked', false);
|
||||
$this.find('.oi-heart').removeClass('text-danger');
|
||||
|
||||
const count = data.ejaculation ? data.ejaculation.likes_count : 0;
|
||||
$this.find('.like-count').text(count ? count : '');
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: '/api/likes/' + encodeURIComponent(targetId),
|
||||
method: 'delete',
|
||||
type: 'json',
|
||||
})
|
||||
.then(callback)
|
||||
.catch(function (xhr: jqXHR) {
|
||||
if (xhr.status === 404) {
|
||||
callback(JSON.parse(xhr.responseText));
|
||||
return;
|
||||
fetchDeleteJson(`/api/likes/${encodeURIComponent(targetId)}`)
|
||||
.then((response) => {
|
||||
if (response.status === 200 || response.status === 404) {
|
||||
return response.json();
|
||||
}
|
||||
throw new ResponseError(response);
|
||||
})
|
||||
.then((data) => {
|
||||
$this.data('liked', false);
|
||||
$this.find('.oi-heart').removeClass('text-danger');
|
||||
|
||||
console.error(xhr);
|
||||
const count = data.ejaculation ? data.ejaculation.likes_count : 0;
|
||||
$this.find('.like-count').text(count ? count : '');
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
alert('いいねを解除できませんでした。');
|
||||
});
|
||||
} else {
|
||||
const callback = (data: any) => {
|
||||
$this.data('liked', true);
|
||||
$this.find('.oi-heart').addClass('text-danger');
|
||||
fetchPostJson('/api/likes', { id: targetId })
|
||||
.then((response) => {
|
||||
if (response.status === 200 || response.status === 409) {
|
||||
return response.json();
|
||||
}
|
||||
throw new ResponseError(response);
|
||||
})
|
||||
.then((data) => {
|
||||
$this.data('liked', true);
|
||||
$this.find('.oi-heart').addClass('text-danger');
|
||||
|
||||
const count = data.ejaculation ? data.ejaculation.likes_count : 0;
|
||||
$this.find('.like-count').text(count ? count : '');
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: '/api/likes',
|
||||
method: 'post',
|
||||
type: 'json',
|
||||
data: {
|
||||
id: targetId,
|
||||
},
|
||||
})
|
||||
.then(callback)
|
||||
.catch(function (xhr: jqXHR) {
|
||||
if (xhr.status === 409) {
|
||||
callback(JSON.parse(xhr.responseText));
|
||||
return;
|
||||
} else if (xhr.status === 401) {
|
||||
const count = data.ejaculation ? data.ejaculation.likes_count : 0;
|
||||
$this.find('.like-count').text(count ? count : '');
|
||||
})
|
||||
.catch((e) => {
|
||||
if (e instanceof ResponseError && e.response.status === 401) {
|
||||
alert('いいねするためにはログインしてください。');
|
||||
return;
|
||||
}
|
||||
|
||||
console.error(xhr);
|
||||
console.error(e);
|
||||
alert('いいねできませんでした。');
|
||||
});
|
||||
}
|
||||
|
@@ -1,17 +1,5 @@
|
||||
// jQuery
|
||||
import './tissue';
|
||||
|
||||
// Setup global request header
|
||||
const token = document.head.querySelector<HTMLMetaElement>('meta[name="csrf-token"]');
|
||||
if (!token) {
|
||||
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
|
||||
} else {
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': token.content,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Bootstrap
|
||||
import 'bootstrap';
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import Vue from 'vue';
|
||||
import TagInput from './components/TagInput.vue';
|
||||
import MetadataPreview from './components/MetadataPreview.vue';
|
||||
import { fetchGet, ResponseError } from './fetch';
|
||||
|
||||
export const bus = new Vue({ name: 'EventBus' });
|
||||
|
||||
@@ -47,19 +48,18 @@ new Vue({
|
||||
fetchMetadata(url: string) {
|
||||
this.metadataLoadState = MetadataLoadState.Loading;
|
||||
|
||||
$.ajax({
|
||||
url: '/api/checkin/card',
|
||||
method: 'get',
|
||||
type: 'json',
|
||||
data: {
|
||||
url,
|
||||
},
|
||||
})
|
||||
fetchGet('/api/checkin/card', { url })
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new ResponseError(response);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((data) => {
|
||||
this.metadata = data;
|
||||
this.metadataLoadState = MetadataLoadState.Success;
|
||||
})
|
||||
.catch((_e) => {
|
||||
.catch(() => {
|
||||
this.metadata = null;
|
||||
this.metadataLoadState = MetadataLoadState.Failed;
|
||||
});
|
||||
|
@@ -41,7 +41,7 @@ export default class TagInput extends Vue {
|
||||
case 'Enter':
|
||||
case ' ':
|
||||
if ((event as any).isComposing !== true) {
|
||||
this.tags.push(this.buffer.trim());
|
||||
this.tags.push(this.buffer.trim().replace(/\s+/g, '_'));
|
||||
this.buffer = '';
|
||||
}
|
||||
event.preventDefault();
|
||||
@@ -49,7 +49,7 @@ export default class TagInput extends Vue {
|
||||
case 'Unidentified':
|
||||
// 実際にテキストボックスに入力されている文字を見に行く (フォールバック処理)
|
||||
if (event.srcElement && (event.srcElement as HTMLInputElement).value.slice(-1) == ' ') {
|
||||
this.tags.push(this.buffer.trim());
|
||||
this.tags.push(this.buffer.trim().replace(/\s+/g, '_'));
|
||||
this.buffer = '';
|
||||
event.preventDefault();
|
||||
}
|
||||
|
71
resources/assets/js/fetch.ts
Normal file
71
resources/assets/js/fetch.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { stringify } from 'qs';
|
||||
|
||||
const token = document.head.querySelector<HTMLMetaElement>('meta[name="csrf-token"]');
|
||||
if (!token) {
|
||||
console.error('CSRF token not found');
|
||||
}
|
||||
|
||||
const headers = {
|
||||
'X-CSRF-TOKEN': token?.content ?? '',
|
||||
};
|
||||
|
||||
type QueryParams = { [key: string]: string };
|
||||
|
||||
const joinParamsToPath = (path: string, params: QueryParams) =>
|
||||
Object.keys(params).length === 0 ? path : `${path}?${stringify(params)}`;
|
||||
|
||||
const fetchWrapper = (path: string, options: RequestInit = {}) =>
|
||||
fetch(path, {
|
||||
credentials: 'same-origin',
|
||||
...options,
|
||||
headers: { ...headers, ...options.headers },
|
||||
});
|
||||
|
||||
const fetchWithJson = (path: string, body?: any, options: RequestInit = {}) =>
|
||||
fetchWrapper(path, {
|
||||
...options,
|
||||
body: body && JSON.stringify(body),
|
||||
headers: { 'Content-Type': 'application/json', ...options.headers },
|
||||
});
|
||||
|
||||
const fetchWithForm = (path: string, body?: any, options: RequestInit = {}) =>
|
||||
fetchWrapper(path, {
|
||||
...options,
|
||||
body: body && stringify(body),
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded', ...options.headers },
|
||||
});
|
||||
|
||||
export const fetchGet = (path: string, params: QueryParams = {}, options: RequestInit = {}) =>
|
||||
fetchWrapper(joinParamsToPath(path, params), { method: 'GET', ...options });
|
||||
|
||||
export const fetchPostJson = (path: string, body?: any, options: RequestInit = {}) =>
|
||||
fetchWithJson(path, body, { method: 'POST', ...options });
|
||||
|
||||
export const fetchPostForm = (path: string, body?: any, options: RequestInit = {}) =>
|
||||
fetchWithForm(path, body, { method: 'POST', ...options });
|
||||
|
||||
export const fetchPutJson = (path: string, body?: any, options: RequestInit = {}) =>
|
||||
fetchWithJson(path, body, { method: 'PUT', ...options });
|
||||
|
||||
export const fetchPutForm = (path: string, body?: any, options: RequestInit = {}) =>
|
||||
fetchWithForm(path, body, { method: 'PUT', ...options });
|
||||
|
||||
export const fetchDeleteJson = (path: string, body?: any, options: RequestInit = {}) =>
|
||||
fetchWithJson(path, body, { method: 'DELETE', ...options });
|
||||
|
||||
export const fetchDeleteForm = (path: string, body?: any, options: RequestInit = {}) =>
|
||||
fetchWithForm(path, body, { method: 'DELETE', ...options });
|
||||
|
||||
export class ResponseError extends Error {
|
||||
response: Response;
|
||||
|
||||
constructor(response: Response, ...rest: any) {
|
||||
super(...rest);
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, ResponseError);
|
||||
}
|
||||
|
||||
this.name = 'ResponseError';
|
||||
this.response = response;
|
||||
}
|
||||
}
|
@@ -1,3 +1,5 @@
|
||||
import { fetchGet } from './fetch';
|
||||
|
||||
(function ($) {
|
||||
$.fn.linkCard = function (options) {
|
||||
const settings = $.extend(
|
||||
@@ -9,43 +11,44 @@
|
||||
|
||||
return this.each(function () {
|
||||
const $this = $(this);
|
||||
$.ajax({
|
||||
url: settings.endpoint,
|
||||
method: 'get',
|
||||
type: 'json',
|
||||
data: {
|
||||
url: $this.find('a').attr('href'),
|
||||
},
|
||||
}).then(function (data) {
|
||||
const $metaColumn = $this.find('.col-12:last-of-type');
|
||||
const $imageColumn = $this.find('.col-12:first-of-type');
|
||||
const $title = $this.find('.card-title');
|
||||
const $desc = $this.find('.card-text');
|
||||
const $image = $imageColumn.find('img');
|
||||
|
||||
if (data.title === '') {
|
||||
$title.hide();
|
||||
} else {
|
||||
$title.text(data.title);
|
||||
}
|
||||
const url = $this.find('a').attr('href');
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.description === '') {
|
||||
$desc.hide();
|
||||
} else {
|
||||
$desc.text(data.description);
|
||||
}
|
||||
fetchGet(settings.endpoint, { url })
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
const $metaColumn = $this.find('.col-12:last-of-type');
|
||||
const $imageColumn = $this.find('.col-12:first-of-type');
|
||||
const $title = $this.find('.card-title');
|
||||
const $desc = $this.find('.card-text');
|
||||
const $image = $imageColumn.find('img');
|
||||
|
||||
if (data.image === '') {
|
||||
$imageColumn.hide();
|
||||
$metaColumn.removeClass('col-md-6');
|
||||
} else {
|
||||
$image.attr('src', data.image);
|
||||
}
|
||||
if (data.title === '') {
|
||||
$title.hide();
|
||||
} else {
|
||||
$title.text(data.title);
|
||||
}
|
||||
|
||||
if (data.title !== '' || data.description !== '' || data.image !== '') {
|
||||
$this.removeClass('d-none');
|
||||
}
|
||||
});
|
||||
if (data.description === '') {
|
||||
$desc.hide();
|
||||
} else {
|
||||
$desc.text(data.description);
|
||||
}
|
||||
|
||||
if (data.image === '') {
|
||||
$imageColumn.hide();
|
||||
$metaColumn.removeClass('col-md-6');
|
||||
} else {
|
||||
$image.attr('src', data.image);
|
||||
}
|
||||
|
||||
if (data.title !== '' || data.description !== '' || data.image !== '') {
|
||||
$this.removeClass('d-none');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user