VK Group Stats, v1.1.0
Posted on

Service for a collecting of a VK groups stats.
Split to pages, add an user profile, request additional counters.
Change Log
- Closed issues:
- Force RU lang in VK API requests #38
- Request additional counters #37
- Support a requesting of an additional counter for a range #36
- Disable «Reload» and «Add group» menu items on not groups pages #35
- Add a profile update #34
- Add a profile view #33
- Add a profile page #32
- Update of new user fields on a login #31
- Support an update of new user fields #30
- Extend the user model: add a name, a screen name and a photo #29
- Add additional margins to single cards #28
- Move a login processing from the MainMenu component to the AppBar component #27
- Remove the about app dialog #25
- Add a side menu for a routes navigation #22
- Separate the about info to a single page #21
- Fixed bugs:
Features
- back-end:
- authentication:
- an authentication via VK;
- support of a skipping of an authentication;
- users:
- data:
- operations:
- support of a fake user on a skipping of an authentication;
- groups:
- counters:
- data:
- MongoDB ObjectId;
- group ObjectId;
- addition timestamp;
- group members counter;
- operations (for a specified group):
- getting of all in a descending order;
- getting of all in a descending order beginning with a specified timestamp;
- getting of an additional counter after all requested counters;
- addition of one via VK API;
- deletion of all;
- data:
- automatically addition of counters via VK API for all added groups by schedule;
- authentication:
- front-end:
- design:
- adaptive;
- material:
- dark;
- light;
- pages:
- group list:
- displays:
- groups;
- states:
- fetching;
- success;
- failure;
- for every group:
- add group dialog;
- simultaneously for all groups:
- reloading;
- update;
- displays:
- user profile:
- info about app;
- group list:
- authentication:
- login;
- logout.
- design:
API
API description in the Swagger format:
swagger: '2.0'
info:
title: vk-group-stats
version: 1.1.0
basePath: /api/v1
schemes:
- http
- https
consumes:
- application/x-www-form-urlencoded
- application/json
produces:
- application/json
paths:
/groups:
get:
responses:
200:
description: OK
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/definitions/group'
required:
- data
401:
description: Unauthorized
schema:
$ref: '#/definitions/error'
500:
description: Internal Server Error
schema:
$ref: '#/definitions/error'
post:
parameters:
- $ref: '#/parameters/group_form'
responses:
200:
description: OK
schema:
type: object
properties:
data:
type: object
properties:
group:
$ref: '#/definitions/group'
counter:
$ref: '#/definitions/counter'
required:
- group
- counter
required:
- data
400:
description: Bad Request
schema:
$ref: '#/definitions/error'
401:
description: Unauthorized
schema:
$ref: '#/definitions/error'
500:
description: Internal Server Error
schema:
$ref: '#/definitions/error'
/groups/{group_id}:
parameters:
- $ref: '#/parameters/group_id'
delete:
responses:
200:
description: OK
schema:
$ref: '#/definitions/ok'
400:
description: Bad Request
schema:
$ref: '#/definitions/error'
401:
description: Unauthorized
schema:
$ref: '#/definitions/error'
500:
description: Internal Server Error
schema:
$ref: '#/definitions/error'
/groups/{group_id}/counters:
parameters:
- $ref: '#/parameters/group_id'
get:
parameters:
- $ref: '#/parameters/start_timestamp'
- $ref: '#/parameters/additional_counter'
responses:
200:
description: OK
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/definitions/counter'
required:
- data
400:
description: Bad Request
schema:
$ref: '#/definitions/error'
401:
description: Unauthorized
schema:
$ref: '#/definitions/error'
500:
description: Internal Server Error
schema:
$ref: '#/definitions/error'
post:
responses:
200:
description: OK
schema:
type: object
properties:
data:
type: object
properties:
group:
$ref: '#/definitions/group'
counter:
$ref: '#/definitions/counter'
required:
- group
- counter
required:
- data
400:
description: Bad Request
schema:
$ref: '#/definitions/error'
401:
description: Unauthorized
schema:
$ref: '#/definitions/error'
500:
description: Internal Server Error
schema:
$ref: '#/definitions/error'
/users/me:
get:
responses:
200:
description: OK
schema:
type: object
properties:
data:
$ref: '#/definitions/user'
required:
- data
500:
description: Internal Server Error
schema:
$ref: '#/definitions/error'
post:
responses:
200:
description: OK
schema:
type: object
properties:
data:
$ref: '#/definitions/user'
required:
- data
401:
description: Unauthorized
schema:
$ref: '#/definitions/error'
500:
description: Internal Server Error
schema:
$ref: '#/definitions/error'
parameters:
group_id:
name: group_id
in: path
required: true
type: string
format: mongodb-objectid
pattern: ^[0-9A-Fa-f]+$
minLength: 24
maxLength: 24
group_form:
name: body
in: body
required: true
schema:
$ref: '#/definitions/group_form'
start_timestamp:
name: start_timestamp
in: query
type: string
format: iso8601-timestamp
pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$
additional_counter:
name: additional_counter
in: query
type: boolean
definitions:
group_form:
type: object
properties:
screen_name:
type: string
required:
- screen_name
group:
type: object
properties:
_id:
$ref: '#/definitions/mongodb-objectid'
user_id:
$ref: '#/definitions/mongodb-objectid'
photo:
type: string
name:
type: string
screen_name:
type: string
required:
- _id
- user_id
- screen_name
counter:
type: object
properties:
_id:
$ref: '#/definitions/mongodb-objectid'
group_id:
$ref: '#/definitions/mongodb-objectid'
timestamp:
type: string
description: date and time in ISO 8601 format
pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$
value:
type: integer
minimum: 0
required:
- _id
- group_id
- timestamp
- value
user:
type: object
description: may be null
properties:
_id:
$ref: '#/definitions/mongodb-objectid'
vk_id:
type: integer
minimum: 0
photo:
type: string
name:
type: string
screen_name:
type: string
required:
- _id
- vk_id
ok:
type: object
properties:
data:
type: boolean
description: always true
required:
- data
error:
type: object
properties:
errors:
type: array
minItems: 1
items:
type: object
properties:
message:
type: string
field:
type: string
required:
- message
required:
- errors
mongodb-objectid:
type: string
pattern: ^[0-9A-Fa-f]+$
minLength: 24
maxLength: 24
Redux state
Redux state in the JSON Schema format:
{
"type": "object",
"properties": {
"login": {
"type": "object",
"properties": {
"state": {
"$ref": "#/definitions/state"
},
"isLogged": {
"type": "boolean"
},
"user": {
"type": "object",
"properties": {
"state": {
"$ref": "#/definitions/state"
},
"data": {
"$ref": "#/definitions/user"
}
},
"required": [
"state",
"data"
]
}
},
"required": [
"state",
"isLogged"
]
},
"sideMenu": {
"$ref": "#/definitions/openable"
},
"groupDialog": {
"$ref": "#/definitions/openable"
},
"groups": {
"type": "object",
"properties": {
"state": {
"$ref": "#/definitions/state"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"state": {
"$ref": "#/definitions/state"
},
"data": {
"$ref": "#/definitions/group"
},
"counters": {
"type": "object",
"properties": {
"state": {
"$ref": "#/definitions/state"
},
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/counter"
}
}
},
"required": [
"state",
"items"
]
}
},
"required": [
"state",
"data",
"counters"
]
}
}
},
"required": [
"state",
"items"
]
}
},
"required": [
"login",
"sideMenu",
"groupDialog",
"groups"
],
"definitions": {
"openable": {
"type": "object",
"properties": {
"open": {
"type": "boolean"
}
},
"required": [
"open"
]
},
"state": {
"type": "string",
"enum": [
"fetching",
"success",
"failure"
],
"default": "success"
},
"group": {
"type": "object",
"properties": {
"_id": {
"$ref": "#/definitions/mongodb-objectid"
},
"photo": {
"type": "string"
},
"name": {
"type": "string"
},
"screen_name": {
"type": "string"
}
},
"required": [
"_id",
"screen_name"
]
},
"counter": {
"type": "object",
"properties": {
"_id": {
"$ref": "#/definitions/mongodb-objectid"
},
"timestamp": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.\\d{3}Z$"
},
"value": {
"$ref": "#/definitions/positive-integer"
},
"delta": {
"type": "integer"
}
},
"required": [
"_id",
"timestamp",
"value"
]
},
"user": {
"type": "object",
"properties": {
"_id": {
"$ref": "#/definitions/mongodb-objectid"
},
"vk_id": {
"$ref": "#/definitions/positive-integer"
},
"photo": {
"type": "string"
},
"name": {
"type": "string"
},
"screen_name": {
"type": "string"
}
},
"required": [
"_id",
"vk_id"
]
},
"mongodb-objectid": {
"type": "string",
"pattern": "^[0-9A-Fa-f]+$",
"minLength": 24,
"maxLength": 24
},
"positive-integer": {
"type": "integer",
"minimum": 0
}
}
}
Repository
Link: https://github.com/thewizardplusplus/vk-group-stats/tree/v1.1.0.
Content: code.
License: MIT.
Screenshots
GET /groups/{group_id}/counters

GET /users/me

POST /users/me

Main menu (unauthorized)

Main menu (authorized)

User profile
