Skip to content

Commit

Permalink
Geofences and GeofenceToNodes (#609)
Browse files Browse the repository at this point in the history
* implement api [wip]

* implement api [wip]

* add postbatch, update types and methods

* update README.md

---------

Co-authored-by: kaveh.taher <[email protected]>
  • Loading branch information
kawehtaher1989 and kaveh.taher authored Nov 28, 2023
1 parent 2e39491 commit a73d0a9
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 2 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ async() => {
- [ ] [files](https://api.timetac.com/doc/v3#tag/files)
- [ ] [generalSettingsChangeLog](https://api.timetac.com/doc/v3#tag/generalSettingsChangeLog)
- [x] [generalSettings](https://api.timetac.com/doc/v3#tag/generalSettings)
- [ ] [geofences](https://api.timetac.com/doc/v3#tag/geofences)
- [ ] [geofenceToNodes](https://api.timetac.com/doc/v3#tag/geofenceToNodes)
- [x] [geofences](https://api.timetac.com/doc/v3#tag/geofences)
- [x] [geofenceToNodes](https://api.timetac.com/doc/v3#tag/geofenceToNodes)
- [ ] [invoices](https://api.timetac.com/doc/v3#tag/invoices)
- [ ] [JobParams](https://api.timetac.com/doc/v3#tag/JobParams)
- [x] [JobQueues](https://api.timetac.com/doc/v3#tag/JobQueues)
Expand Down
12 changes: 12 additions & 0 deletions src/baseApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,18 @@ export default abstract class BaseApi<ResourceName extends ResourceNames> {
return axios.put<ApiBatchResponse<ResourceName>>(url, { ...data, ...params }, config);
}

protected _postBatch<ResourceName extends ResourceNames>(
slug: string,
// eslint-disable-next-line @typescript-eslint/ban-types
data?: object,
params?: RequestParams<Entity<ResourceName>>,
options?: AxiosRequestConfig,
) {
const url = `${this.getBaseEndpointUrl()}${slug}`;
const config = this.getOptions(options);
return axios.post<ApiBatchResponse<ResourceName>>(url, { ...data, ...params }, config);
}

protected _delete<ResourceName extends ResourceNames>(slug: string, options?: AxiosRequestConfig): RequestPromise<ResourceName> {
const url = `${this.getBaseEndpointUrl()}${slug}`;
const config = this.getOptions(options);
Expand Down
36 changes: 36 additions & 0 deletions src/geoFences/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import BaseApi from '../baseApi';
import { RequestParams } from '../utils/params/requestParams';
import { Entity, LibraryReturn, Resources } from '../utils/response/apiResponse';
import { list, required, Required, requiredSingle } from '../utils/response/responseHandlers';
import { GeofenceCreate, GeofenceUpdate } from './types';

const resourceName = 'geofences';
type ResourceName = typeof resourceName;

export class GeofenceEndpoint extends BaseApi<ResourceName> {
public readonly resourceName = resourceName;
public read(
params?: RequestParams<Entity<typeof resourceName>> | string,
): Promise<LibraryReturn<typeof resourceName, Entity<typeof resourceName>[]>> {
const response = this._get<typeof resourceName>('read', { params });
return list(response);
}

public create(data: GeofenceCreate, params?: RequestParams<Entity<ResourceName>>): Required<ResourceName> {
const response = this._post<ResourceName>('create', data, params);
return requiredSingle(response);
}

public update(
data: GeofenceUpdate,
params?: RequestParams<Entity<ResourceName>>,
): Required<typeof resourceName, Resources[typeof resourceName][]> {
const response = this._put<ResourceName>('update', data, params);
return required(response);
}

public delete(id: number): Promise<LibraryReturn<typeof resourceName>> {
const response = this._delete<typeof resourceName>(`delete`, { params: { id } });
return requiredSingle(response);
}
}
15 changes: 15 additions & 0 deletions src/geoFences/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
type Geofence = {
id: number;
name: string;
geo_lat: number;
geo_long: number;
radius: number;
is_demo_data: boolean;
updated: string;
};

export type GeofenceRead = Geofence;

export type GeofenceCreate = Pick<Geofence, 'name' | 'geo_lat' | 'geo_long' | 'radius'> & Partial<Pick<Geofence, 'updated'>>;

export type GeofenceUpdate = Pick<Geofence, 'id'> & Pick<Partial<Geofence>, 'name' | 'geo_lat' | 'geo_long' | 'radius' | 'updated'>;
44 changes: 44 additions & 0 deletions src/geofenceToNodes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import BaseApi from '../baseApi';
import { Entity, LibraryReturn, Resources } from '../utils/response/apiResponse';
import { RequestParams } from '../utils/params/requestParams';
import { list, ParsedErrorMesage, required, Required, requiredBatch, requiredSingle } from '../utils/response/responseHandlers';
import { GeofenceToNodes, GeofenceToNodesCreate, GeofenceToNodesUpdate } from './types';

const resourceName = 'geofenceToNodes';
type ResourceName = typeof resourceName;

export class GeofenceToNodesEndpoint extends BaseApi<ResourceName> {
public readonly resourceName = resourceName;

public read(
params?: RequestParams<Entity<typeof resourceName>> | string,
): Promise<LibraryReturn<typeof resourceName, Entity<typeof resourceName>[]>> {
const response = this._get<typeof resourceName>('read', { params });
return list(response);
}

public create(
data: GeofenceToNodesCreate | GeofenceToNodesCreate[],
params?: RequestParams<Entity<ResourceName>>,
): Promise<LibraryReturn<'geofenceToNodes'>> | Required<'geofenceToNodes', (GeofenceToNodes | ParsedErrorMesage)[]> {
if (Array.isArray(data)) {
const response = this._postBatch<ResourceName>('create', data, params);
return requiredBatch(response);
}
const response = this._post<ResourceName>('create', data, params);
return requiredSingle(response);
}

public update(
data: GeofenceToNodesUpdate,
params?: RequestParams<Entity<ResourceName>>,
): Required<typeof resourceName, Resources[typeof resourceName][]> {
const response = this._put<ResourceName>('update', data, params);
return required(response);
}

public delete(id: number): Promise<LibraryReturn<typeof resourceName>> {
const response = this._delete<typeof resourceName>(`delete`, { params: { id } });
return requiredSingle(response);
}
}
12 changes: 12 additions & 0 deletions src/geofenceToNodes/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export type GeofenceToNodes = {
id: number;
geofence_id: number;
node_id: number;
updated: string;
};

export type GeofenceToNodesRead = GeofenceToNodes;

export type GeofenceToNodesUpdate = Pick<GeofenceToNodes, 'id' | 'node_id' | 'updated'>;

export type GeofenceToNodesCreate = Pick<GeofenceToNodes, 'geofence_id' | 'node_id'> & Partial<Pick<GeofenceToNodes, 'updated'>>;
8 changes: 8 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ import { MonitoringRuleTemplatesEndpoint } from './monitoringRule/monitoringRule
import { MonitoringRuleRecipientsEndpoint } from './monitoringRule/monitoringRuleRecipients';
import { MonitoringRuleIntervalsEndpoint } from './monitoringRule/monitoringRuleIntervals';
import { MonitoringRuleFrequenciesEndpoint } from './monitoringRule/monitoringRuleFrequencies';
import { GeofenceEndpoint } from './geoFences';
import { GeofenceToNodesEndpoint } from './geofenceToNodes';

export { AbsenceBan } from './absenceBans/types';
export { AbsenceDay } from './absenceDays/types';
Expand Down Expand Up @@ -140,6 +142,8 @@ export {
Resources,
resourceNameArray,
} from './utils/response/apiResponse';
export { GeofenceRead, GeofenceCreate, GeofenceUpdate } from './geoFences/types';
export { GeofenceToNodesRead, GeofenceToNodesCreate, GeofenceToNodesUpdate, GeofenceToNodes } from './geofenceToNodes/types';
export { DeltaSyncResponse } from './utils/response/deltaSyncResponse';
export { RawApiResponse } from './utils/response/rawApiResponse';
export { ReadRawResponse } from './utils/response/readRawResponse';
Expand Down Expand Up @@ -180,6 +184,8 @@ export default class Api {
public favouriteTasks: FavouriteTasksEndpoint;
public feedback: FeedbackEndpoint;
public generalSettings: GeneralSettingsEndpoint;
public geofence: GeofenceEndpoint;
public geofenceToNodes: GeofenceToNodesEndpoint;
public healthRules: HealthRulesEndpoint;
public healthData: HealthDataEndpoint;
public projects: ProjectsEndpoint;
Expand Down Expand Up @@ -297,6 +303,8 @@ export default class Api {
this.monitoringRuleFrequencies = new MonitoringRuleFrequenciesEndpoint(this.config);
this.monitoringRuleTemplates = new MonitoringRuleTemplatesEndpoint(this.config);
this.monitoringRuleRecipients = new MonitoringRuleRecipientsEndpoint(this.config);
this.geofence = new GeofenceEndpoint(this.config);
this.geofenceToNodes = new GeofenceToNodesEndpoint(this.config);
useInterceptors({ state: this.state, config: this.config, authentication: this.authentication });
}

Expand Down
6 changes: 6 additions & 0 deletions src/utils/response/apiResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ import { MonitoringRuleFrequencyRead } from '../../monitoringRule/monitoringRule
import { MonitoringRuleIntervalsRead } from '../../monitoringRule/monitoringRuleIntervals/types';
import { MonitoringRuleRecipientsRead } from '../../monitoringRule/monitoringRuleRecipients/types';
import { MonitoringRuleTemplatesRead } from '../../monitoringRule/monitoringRuleTemplates/types';
import { GeofenceRead } from '../../geoFences/types';
import { GeofenceToNodesRead } from '../../geofenceToNodes/types';

// Because types cannot be iterated at runtime, we add the keys of Resources here as a value
// Below we add conditional types that don't compile if this array and Resources go out of sync
Expand Down Expand Up @@ -113,6 +115,8 @@ export const resourceNameArray = [
'monitoringRuleIntervals',
'monitoringRuleRecipients',
'monitoringRuleTemplates',
'geofences',
'geofenceToNodes',
] as const;

export type Resources = {
Expand Down Expand Up @@ -190,6 +194,8 @@ export type Resources = {
monitoringRuleIntervals: MonitoringRuleIntervalsRead;
monitoringRuleRecipients: MonitoringRuleRecipientsRead;
monitoringRuleTemplates: MonitoringRuleTemplatesRead;
geofences: GeofenceRead;
geofenceToNodes: GeofenceToNodesRead;
};

// These conditional types ensure that the resourceNameArray and the Resources type are in sync
Expand Down

0 comments on commit a73d0a9

Please sign in to comment.