World Conquest Chronicles

World Conquest Chronicles

VK Group Stats, v1.1.0

Side menu

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:
    • Use theme styles for the main menu button #24
    • Use theme styles for the login button #23

Features

  • back-end:
    • authentication:
      • an authentication via VK;
      • support of a skipping of an authentication;
    • users:
      • data:
        • MongoDB ObjectId;
        • VK ID;
        • VK photo;
        • name (VK first name, VK nickname and VK last name separated by a whitespace symbol);
        • VK screen name;
      • operations:
        • getting of a current user;
        • update of a data via VK API;
        • automatically on an authentication:
          • addition;
          • update of a data via VK API;
      • support of a fake user on a skipping of an authentication;
    • groups:
      • data:
        • MongoDB ObjectId;
        • user ObjectId;
        • VK photo;
        • VK name;
        • VK screen name;
      • operations (for a current user):
        • getting of all;
        • addition of one:
          • by VK screen name;
          • by VK URL;
        • update of one data via VK API;
        • deletion of one;
    • 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;
    • automatically addition of counters via VK API for all added groups by schedule;
  • front-end:
    • design:
      • adaptive;
      • material:
        • dark;
        • light;
    • pages:
      • group list:
        • displays:
          • groups;
        • states:
          • fetching;
          • success;
          • failure;
        • for every group:
          • displays:
            • VK photo;
            • VK name;
            • VK screen name;
            • all counters for a last day and one additional counter after all rest;
          • states:
            • fetching;
            • success;
            • failure;
          • for every counter:
            • displays:
              • timestamp;
              • number of subscribers;
              • delta compared to a previous (optionally);
        • add group dialog;
        • simultaneously for all groups:
          • reloading;
          • update;
      • user profile:
        • displays:
          • VK photo;
          • name (VK first name, VK nickname and VK last name separated by a whitespace symbol);
          • VK screen name;
          • VK ID (optionally);
        • states:
          • fetching;
          • success;
          • failure;
      • info about app;
    • authentication:
      • login;
      • logout.

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 /groups/{group_id}/counters

GET /users/me

GET /users/me

POST /users/me

POST /users/me

Main menu (unauthorized)

Main menu (unauthorized)

Main menu (authorized)

Main menu (authorized)

User profile

User profile