mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-21 07:03:49 +00:00
wip on app2
This commit is contained in:
@@ -24,7 +24,7 @@ require('./chillmain.scss');
|
||||
import { chill } from './js/chill.js';
|
||||
global.chill = chill;
|
||||
|
||||
require('./js/date.js');
|
||||
require('./js/date');
|
||||
require('./js/counter.js');
|
||||
|
||||
/// Load fonts
|
||||
|
@@ -12,7 +12,7 @@
|
||||
* Do not take time into account
|
||||
*
|
||||
*/
|
||||
const dateToISO = (date) => {
|
||||
export const dateToISO = (date: Date|null): string|null => {
|
||||
if (null === date) {
|
||||
return null;
|
||||
}
|
||||
@@ -29,7 +29,7 @@ const dateToISO = (date) => {
|
||||
*
|
||||
* **Experimental**
|
||||
*/
|
||||
const ISOToDate = (str) => {
|
||||
export const ISOToDate = (str: string|null): Date|null => {
|
||||
if (null === str) {
|
||||
return null;
|
||||
}
|
||||
@@ -38,7 +38,7 @@ const ISOToDate = (str) => {
|
||||
}
|
||||
|
||||
let
|
||||
[year, month, day] = str.split('-');
|
||||
[year, month, day] = str.split('-').map(p => parseInt(p));
|
||||
|
||||
return new Date(year, month-1, day);
|
||||
}
|
||||
@@ -47,16 +47,16 @@ const ISOToDate = (str) => {
|
||||
* Return a date object from iso string formatted as YYYY-mm-dd:HH:MM:ss+01:00
|
||||
*
|
||||
*/
|
||||
const ISOToDatetime = (str) => {
|
||||
export const ISOToDatetime = (str: string|null): Date|null => {
|
||||
if (null === str) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let
|
||||
[cal, times] = str.split('T'),
|
||||
[year, month, date] = cal.split('-'),
|
||||
[year, month, date] = cal.split('-').map(s => parseInt(s)),
|
||||
[time, timezone] = times.split(times.charAt(8)),
|
||||
[hours, minutes, seconds] = time.split(':')
|
||||
[hours, minutes, seconds] = time.split(':').map(s => parseInt(s));
|
||||
;
|
||||
|
||||
return new Date(year, month-1, date, hours, minutes, seconds);
|
||||
@@ -66,7 +66,7 @@ const ISOToDatetime = (str) => {
|
||||
* Convert a date to ISO8601, valid for usage in api
|
||||
*
|
||||
*/
|
||||
const datetimeToISO = (date) => {
|
||||
export const datetimeToISO = (date: Date): string => {
|
||||
let cal, time, offset;
|
||||
cal = [
|
||||
date.getFullYear(),
|
||||
@@ -92,7 +92,7 @@ const datetimeToISO = (date) => {
|
||||
return x;
|
||||
};
|
||||
|
||||
const intervalDaysToISO = (days) => {
|
||||
export const intervalDaysToISO = (days: number|string|null): string => {
|
||||
if (null === days) {
|
||||
return 'P0D';
|
||||
}
|
||||
@@ -100,7 +100,7 @@ const intervalDaysToISO = (days) => {
|
||||
return `P${days}D`;
|
||||
}
|
||||
|
||||
const intervalISOToDays = (str) => {
|
||||
export const intervalISOToDays = (str: string|null): number|null => {
|
||||
if (null === str) {
|
||||
return null
|
||||
}
|
||||
@@ -154,12 +154,3 @@ const intervalISOToDays = (str) => {
|
||||
|
||||
return days;
|
||||
}
|
||||
|
||||
export {
|
||||
dateToISO,
|
||||
ISOToDate,
|
||||
ISOToDatetime,
|
||||
datetimeToISO,
|
||||
intervalISOToDays,
|
||||
intervalDaysToISO,
|
||||
};
|
@@ -1,3 +1,4 @@
|
||||
export function fetchResults<T>(uri: string, params: {item_per_page?: number}): Promise<T[]>;
|
||||
|
||||
export function makeFetch<T, B>(method: "GET"|"POST"|"PATCH"|"DELETE", url: string, body: B, options: {[key: string]: string}): Promise<T>;
|
||||
|
@@ -1,110 +0,0 @@
|
||||
/**
|
||||
* Generic api method that can be adapted to any fetch request
|
||||
*/
|
||||
const makeFetch = (method, url, body, options) => {
|
||||
let opts = {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
body: (body !== null) ? JSON.stringify(body) : null
|
||||
};
|
||||
|
||||
if (typeof options !== 'undefined') {
|
||||
opts = Object.assign(opts, options);
|
||||
}
|
||||
|
||||
return fetch(url, opts)
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
|
||||
if (response.status === 422) {
|
||||
return response.json().then(response => {
|
||||
throw ValidationException(response)
|
||||
});
|
||||
}
|
||||
|
||||
if (response.status === 403) {
|
||||
throw AccessException(response);
|
||||
}
|
||||
|
||||
throw {
|
||||
name: 'Exception',
|
||||
sta: response.status,
|
||||
txt: response.statusText,
|
||||
err: new Error(),
|
||||
violations: response.body
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch results with certain parameters
|
||||
*/
|
||||
const _fetchAction = (page, uri, params) => {
|
||||
const item_per_page = 50;
|
||||
if (params === undefined) {
|
||||
params = {};
|
||||
}
|
||||
let url = uri + '?' + new URLSearchParams({ item_per_page, page, ...params });
|
||||
|
||||
return fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
}).then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw new Error({ m: response.statusText });
|
||||
});
|
||||
};
|
||||
|
||||
const fetchResults = async (uri, params) => {
|
||||
let promises = [],
|
||||
page = 1;
|
||||
let firstData = await _fetchAction(page, uri, params);
|
||||
|
||||
promises.push(Promise.resolve(firstData.results));
|
||||
|
||||
if (firstData.pagination.more) {
|
||||
do {
|
||||
page = ++page;
|
||||
promises.push(_fetchAction(page, uri, params).then(r => Promise.resolve(r.results)));
|
||||
} while (page * firstData.pagination.items_per_page < firstData.count)
|
||||
}
|
||||
|
||||
return Promise.all(promises).then(values => values.flat());
|
||||
};
|
||||
|
||||
const fetchScopes = () => {
|
||||
return fetchResults('/api/1.0/main/scope.json');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Error objects to be thrown
|
||||
*/
|
||||
const ValidationException = (response) => {
|
||||
const error = {};
|
||||
error.name = 'ValidationException';
|
||||
error.violations = response.violations.map((violation) => `${violation.title}: ${violation.propertyPath}`);
|
||||
error.titles = response.violations.map((violation) => violation.title);
|
||||
error.propertyPaths = response.violations.map((violation) => violation.propertyPath);
|
||||
return error;
|
||||
}
|
||||
|
||||
const AccessException = (response) => {
|
||||
const error = {};
|
||||
error.name = 'AccessException';
|
||||
error.violations = ['You are not allowed to perform this action'];
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
export {
|
||||
makeFetch,
|
||||
fetchResults,
|
||||
fetchScopes
|
||||
}
|
@@ -0,0 +1,164 @@
|
||||
import {Scope} from 'ChillMainAssets/types';
|
||||
|
||||
export type body = {[key: string]: boolean|string|number|null};
|
||||
export type fetchOption = {[key: string]: boolean|string|number|null};
|
||||
|
||||
export interface Params {
|
||||
[key: string]: number|string
|
||||
}
|
||||
|
||||
export interface PaginationResponse<T> {
|
||||
pagination: {
|
||||
more: boolean;
|
||||
items_per_page: number;
|
||||
};
|
||||
results: T[];
|
||||
count: number;
|
||||
}
|
||||
|
||||
export interface FetchParams {
|
||||
[K: string]: string|number|null;
|
||||
};
|
||||
|
||||
export interface ValidationExceptionInterface {
|
||||
name: 'ValidationException';
|
||||
error: object;
|
||||
violations: string[];
|
||||
titles: string[];
|
||||
propertyPaths: string[];
|
||||
}
|
||||
|
||||
export interface ValidationErrorResponse {
|
||||
violations: {
|
||||
title: string;
|
||||
propertyPath: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface AccessExceptionInterface {
|
||||
name: 'AccessException';
|
||||
violations: string[];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generic api method that can be adapted to any fetch request
|
||||
*/
|
||||
export const makeFetch = <T, Q>(method: 'POST'|'GET'|'PUT'|'PATCH'|'DELETE', url: string, body?: body | T | null, options?: FetchParams): Promise<Q> => {
|
||||
let opts = {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
body: (body !== null || typeof body !== 'undefined') ? JSON.stringify(body) : null
|
||||
};
|
||||
|
||||
if (typeof options !== 'undefined') {
|
||||
opts = Object.assign(opts, options);
|
||||
}
|
||||
|
||||
return fetch(url, opts)
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
|
||||
if (response.status === 422) {
|
||||
return response.json().then(response => {
|
||||
throw ValidationException(response)
|
||||
});
|
||||
}
|
||||
|
||||
if (response.status === 403) {
|
||||
throw AccessException(response);
|
||||
}
|
||||
|
||||
throw {
|
||||
name: 'Exception',
|
||||
sta: response.status,
|
||||
txt: response.statusText,
|
||||
err: new Error(),
|
||||
violations: response.body
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch results with certain parameters
|
||||
*/
|
||||
function _fetchAction<T>(page: number, uri: string, params?: FetchParams): Promise<PaginationResponse<T>> {
|
||||
const item_per_page: number = 50;
|
||||
|
||||
let searchParams = new URLSearchParams();
|
||||
searchParams.append('item_per_page', item_per_page.toString());
|
||||
searchParams.append('page', page.toString());
|
||||
|
||||
if (params !== undefined) {
|
||||
Object.keys(params).forEach(key => {
|
||||
let v = params[key];
|
||||
if (typeof v === 'string') {
|
||||
searchParams.append(key, v);
|
||||
} else if (typeof v === 'number') {
|
||||
searchParams.append(key, v.toString());
|
||||
} else if (v === null) {
|
||||
searchParams.append(key, '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let url = uri + '?' + searchParams.toString();
|
||||
|
||||
return fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
}).then((response) => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw new Error(response.statusText);
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchResults = async<T> (uri: string, params?: FetchParams): Promise<T[]> => {
|
||||
let promises: Promise<T[]>[] = [],
|
||||
page = 1;
|
||||
let firstData: PaginationResponse<T> = await _fetchAction(page, uri, params) as PaginationResponse<T>;
|
||||
|
||||
promises.push(Promise.resolve(firstData.results));
|
||||
|
||||
if (firstData.pagination.more) {
|
||||
do {
|
||||
page = ++page;
|
||||
promises.push(
|
||||
_fetchAction<T>(page, uri, params).then(r => Promise.resolve(r.results))
|
||||
);
|
||||
} while (page * firstData.pagination.items_per_page < firstData.count)
|
||||
}
|
||||
|
||||
return Promise.all(promises).then((values) => values.flat());
|
||||
};
|
||||
|
||||
export const fetchScopes = (): Promise<Scope[]> => {
|
||||
return fetchResults('/api/1.0/main/scope.json');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Error objects to be thrown
|
||||
*/
|
||||
const ValidationException = (response: ValidationErrorResponse): ValidationExceptionInterface => {
|
||||
const error = {} as ValidationExceptionInterface;
|
||||
error.name = 'ValidationException';
|
||||
error.violations = response.violations.map((violation) => `${violation.title}: ${violation.propertyPath}`);
|
||||
error.titles = response.violations.map((violation) => violation.title);
|
||||
error.propertyPaths = response.violations.map((violation) => violation.propertyPath);
|
||||
return error;
|
||||
}
|
||||
|
||||
const AccessException = (response: Response): AccessExceptionInterface => {
|
||||
const error = {} as AccessExceptionInterface;
|
||||
error.name = 'AccessException';
|
||||
error.violations = ['You are not allowed to perform this action'];
|
||||
|
||||
return error;
|
||||
}
|
36
src/Bundle/ChillMainBundle/Resources/public/types.ts
Normal file
36
src/Bundle/ChillMainBundle/Resources/public/types.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
export interface DateTime {
|
||||
datetime: string;
|
||||
datetime8601: string
|
||||
}
|
||||
|
||||
export interface Job {
|
||||
id: number;
|
||||
type: "user_job";
|
||||
label: {
|
||||
"fr": string; // could have other key. How to do that in ts ?
|
||||
}
|
||||
}
|
||||
|
||||
export interface Center {
|
||||
id: number;
|
||||
type: "center";
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface Scope {
|
||||
id: number;
|
||||
type: "scope";
|
||||
name: {
|
||||
"fr": string
|
||||
}
|
||||
}
|
||||
|
||||
export interface User {
|
||||
type: "user";
|
||||
id: number;
|
||||
username: string;
|
||||
text: string;
|
||||
email: string;
|
||||
user_job: Job;
|
||||
// todo: mainCenter; mainJob; etc..
|
||||
}
|
@@ -54,7 +54,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { dateToISO, ISOToDate } from 'ChillMainAssets/chill/js/date.js';
|
||||
import { dateToISO, ISOToDate } from 'ChillMainAssets/chill/js/date';
|
||||
import AddressRenderBox from 'ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue';
|
||||
import ActionButtons from './ActionButtons.vue';
|
||||
|
||||
|
@@ -20,7 +20,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {makeFetch} from 'ChillMainAssets/lib/api/apiMethods.js';
|
||||
import {makeFetch} from 'ChillMainAssets/lib/api/apiMethods.ts';
|
||||
|
||||
export default {
|
||||
name: "EntityWorkflowVueSubscriber",
|
||||
|
@@ -41,7 +41,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods.js';
|
||||
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods.ts';
|
||||
|
||||
export default {
|
||||
name: "NotificationReadToggle",
|
||||
|
@@ -55,11 +55,12 @@ const messages = {
|
||||
}
|
||||
};
|
||||
|
||||
const _createI18n = (appMessages) => {
|
||||
const _createI18n = (appMessages: any) => {
|
||||
Object.assign(messages.fr, appMessages.fr);
|
||||
return createI18n({
|
||||
locale: 'fr',
|
||||
fallbackLocale: 'fr',
|
||||
// @ts-ignore
|
||||
datetimeFormats,
|
||||
messages,
|
||||
})
|
Reference in New Issue
Block a user