... | @@ -9,6 +9,116 @@ OLD STUFF: |
... | @@ -9,6 +9,116 @@ OLD STUFF: |
|
[[ Lastly, a $http response interceptor has been defined which will attempt to parse DRF error responses and create a human readable string, which is attached to the promise rejection as `rejection.error`.
|
|
[[ Lastly, a $http response interceptor has been defined which will attempt to parse DRF error responses and create a human readable string, which is attached to the promise rejection as `rejection.error`.
|
|
(e.g. `User.patch(changes).catch(err => alert(err.error));`) ]] -- need to update
|
|
(e.g. `User.patch(changes).catch(err => alert(err.error));`) ]] -- need to update
|
|
|
|
|
|
|
|
MORE OLD STUFF:
|
|
|
|
## Documentation for Custom JS-Data Methods
|
|
|
|
|
|
|
|
### `patch` and `DSPatch` instance method
|
|
|
|
Same as DS.update, but overrides the HTTP Method to use `PATCH`.
|
|
|
|
|
|
|
|
### `list`
|
|
|
|
Used in tandem with DRF's `list_route`. Calling `Resource.list('a_list_route')` yields an object that contains five functions: `get`, `put`, `post`, `patch`, and `paging`.
|
|
|
|
Calling those commands makes the appropriate request to the resource's endpoint concatenated with `a_list_route`.
|
|
|
|
|
|
|
|
### `detail` instance method
|
|
|
|
Used in tandem with DRF's `detail_route`. Operates in the same manner as the `list` method above.
|
|
|
|
|
|
|
|
### `debouncedUpdate`
|
|
|
|
Will update a model at most once per 500 milliseconds. When `debouncedUpdate` is called, it will return the same promise for each debounce period.
|
|
|
|
|
|
|
|
### `paging`
|
|
|
|
Returns a pagination cursor.
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
```
|
|
|
|
paging = User.paging(params, options);
|
|
|
|
paging.init();
|
|
|
|
|
|
|
|
paging.meta; // ->
|
|
|
|
{
|
|
|
|
currentPage, // int, current page (starting from 1)
|
|
|
|
fetchingPage, // int, the page currently being fetched
|
|
|
|
pageCount, // int, number of pages
|
|
|
|
pageSize, // int, instances per page
|
|
|
|
totalCount, // int, the total number of instances in all pages
|
|
|
|
}
|
|
|
|
|
|
|
|
// The instances for paging.meta.currentPage
|
|
|
|
paging.page; // -> [...]
|
|
|
|
|
|
|
|
// All instances that have been fetched by the cursor.
|
|
|
|
paging.all; // -> [...]
|
|
|
|
|
|
|
|
// Loads the next page (and prefetches the next page(s))
|
|
|
|
paging.next(); // -> Promise
|
|
|
|
|
|
|
|
// Loads the previous page (and prefetches)
|
|
|
|
paging.prev(); // -> Promise
|
|
|
|
|
|
|
|
// Loads the requested page, and prefetches the pages before and after that page
|
|
|
|
paging.loadPage(pageNumber, prefetchRadius) // -> Promise
|
|
|
|
|
|
|
|
// Fetches all pages. If parallelBool is true, it sends the request for all pages at the same time.
|
|
|
|
// if parallelBool is false, it fetches a page at a time, but you can also access the results as
|
|
|
|
// they are retrieved at Promise.results, and you can abort the serial request using Promise.abort()
|
|
|
|
paging.fetchAll(parallelBool) // -> Promise
|
|
|
|
|
|
|
|
// True if the cursor is currently on the first page
|
|
|
|
paging.start; // -> Boolean
|
|
|
|
|
|
|
|
// True if the cursor is currently on the last page
|
|
|
|
paging.end; // -> Boolean
|
|
|
|
|
|
|
|
// True if all instances from all pages have been loaded
|
|
|
|
paging.allLoaded // -> Boolean
|
|
|
|
```
|
|
|
|
|
|
|
|
Default Options:
|
|
|
|
```
|
|
|
|
{
|
|
|
|
cacheResponse: true,
|
|
|
|
pageQueryParam: 'page',
|
|
|
|
fetchAll: false,
|
|
|
|
prefetch: 1,
|
|
|
|
}
|
|
|
|
```
|
|
|
|
Additional (non default) Options:
|
|
|
|
{
|
|
|
|
pageSize, // int
|
|
|
|
pageSizeQueryParam, // str
|
|
|
|
list, // str (list_route)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
### `findAllPaged`
|
|
|
|
Uses the `paging` method above, but immediately calls `fetchAll` and returns the result.
|
|
|
|
|
|
|
|
## Using Oauth
|
|
|
|
There are two oauth providers configured by default (Facebook and Google) that belong to the goog-dev@izeni.com accounts.
|
|
|
|
|
|
|
|
To use oauth, you must first locate the correct Python Social Auth provider name (e.g. 'facebook' or 'google-oauth2')
|
|
|
|
|
|
|
|
Then, obtain a client ID and secret from the provider's website (e.g. developers.facebook.com) as well as add a link to the redirect_uri configuration in the format of http(s)://[domain]/oauth/[provider]
|
|
|
|
e.g.
|
|
|
|
```
|
|
|
|
http://local.izeni.net:9000/oauth/facebook
|
|
|
|
or
|
|
|
|
https://izeni.com/oauth/facebook
|
|
|
|
```
|
|
|
|
|
|
|
|
Save the client ID in the appropriate config file under the `oauth` key. It should be in the format of
|
|
|
|
`"provider_name": "client_id"` e.g. `"facebook": "1649988431884827"`
|
|
|
|
|
|
|
|
The secret is _not_ saved on the client.
|
|
|
|
|
|
|
|
To initiate the oauth process, we have to link to the provider's oauth login page using the correct redirect_uri (and scope, if necessary)
|
|
|
|
The `oauth` directive can generate those links using configuration which can be found in `src/app/login/login.js`
|
|
|
|
That configuration requires a `provider` (same as above, e.g. "google-oauth2") a `url`, and optionally a `scope` (which differs with each provider, refer to PSA documentation)
|
|
|
|
|
|
|
|
Lastly, after the user initiates the oauth process, they are redirect back to the `redirect_uri`,
|
|
|
|
which is caught by the `oauth` state. The oauth state then sends a request to the server:
|
|
|
|
`/social/facebook?code=[code]&state=[state]` which then returns a token. If a user didn't exist for the email that the oauth provider passed along, a new user will be created in that same call.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
```typescript
|
|
class Book (models.Model):
|
|
class Book (models.Model):
|
... | | ... | |