Admin user added

This commit is contained in:
tasosgig 2018-11-02 19:31:11 +02:00
parent ca8a7bffc2
commit 18e8b009a0
17 changed files with 14305 additions and 20 deletions

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,7 @@
"ng-focus-if": "^1.0.7",
"ng2-nouislider": "^1.7.7",
"ngx-pagination": "^3.1.0",
"nouislider": "^11.0.3",
"nouislider": "^11.1.0",
"rxjs": "^5.5.6",
"uikit": "^3.0.0-beta.38",
"zone.js": "^0.8.19"

View File

@ -2,7 +2,7 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
export const AppRoutes: Routes = [
{ path: '', redirectTo: '/mining/manage-profiles', pathMatch: 'full' }
{ path: '', redirectTo: '/mining/manage-profiles?communityId=Egi', pathMatch: 'full' }
];
@NgModule({

View File

@ -8,7 +8,8 @@ import { Component, OnInit } from '@angular/core';
export class AppComponent implements OnInit {
private _userid = 'user5649231';
private _backendserveraddress = 'http://localhost:8080';
private _backendserveraddress = 'https://beta.services.openaire.eu/interactive-mining';
private _isCommunityManager = 'true';
title = 'app';
@ -17,5 +18,7 @@ export class AppComponent implements OnInit {
console.log(localStorage.getItem('user_id'), this._userid);
localStorage.setItem('mining_backend_address', this._backendserveraddress);
console.log(localStorage.getItem('mining_backend_address'), this._backendserveraddress);
localStorage.setItem('isCommunityManager', this._isCommunityManager);
console.log(localStorage.getItem('isCommunityManager'), this._isCommunityManager);
}
}

View File

@ -1,9 +1,9 @@
import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {Util} from '../util';
import {Observable} from 'rxjs/Observable';
import {Settings} from './settings/settings';
import {DocSamplesMetadata} from './doc-samples-metadata';
import {Util} from '../util';
@Injectable()
export class ConfigurationService {

View File

@ -1,7 +1,61 @@
<app-stepsnvabar></app-stepsnvabar>
<div *ngIf="isCommunityManager" class="uk-section uk-section-default">
<div class="uk-container uk-container-expand">
<h4>Administrate all profiles <span class="cm-tooltip" uk-icon="icon: info" title="Each <b>mining profile</b> consists of the data and the rules used to define a <b>mining procedure</b>.<br>Click the profile to <b>edit</b>." uk-tooltip="pos: right"></span></h4>
<div class="uk-overflow-auto">
<table class="uk-table uk-table-hover uk-table-middle uk-table-divider">
<thead>
<tr>
<th class="uk-table-small cm-text-muted">Community</th>
<th class="uk-table-expand cm-text-muted">Profile</th>
<th class="uk-table-small cm-text-muted">Modified</th>
<th class="uk-width-small cm-text-muted">Status</th>
<th class="uk-table-shrink"></th>
<!--<th class="uk-table-shrink uk-text-nowrap">Matches</th>-->
</tr>
</thead>
<tfoot>
</tfoot>
<tbody>
<tr *ngFor="let profile of allUsersProfiles | paginate: config; let i = index">
<td class="uk-text-nowrap">{{profile.user}}</td>
<td class="uk-table-link">
<a class="uk-link-reset" (click)="loadUserProfileAdmin(profile.userId, profile.profileId, profile.profile)">{{profile.profile}}</a>
</td>
<td class="cm-text-muted uk-text-nowrap">{{profile.datecreated}}</td>
<td class="uk-text-nowrap uk-text-warning">
<select [(ngModel)]="profile.status" (ngModelChange)="onStatusChange(profile.userId, profile.profileId, $event)">
<option *ngFor="let status of statusValues" [ngValue]="status">{{status}}</option>
</select>
</td>
<td class="download">
<a class="uk-icon-link uk-icon" uk-icon="icon: download" contenteditable="false" (click)="downloadUserProfileAdmin(profile.userId, profile.profileId, profile.profile)"></a>
</td>
<!--<td class="uk-text-nowrap">{{profile.matches}}</td>-->
</tr>
</tbody>
</table>
<pagination-template *ngIf="allUsersProfiles.length" #p="paginationApi"
[id]="config.id"
(pageChange)="config.currentPage = $event">
<ul class="uk-pagination uk-flex-center" uk-margin>
<li [class.uk-disabled]="p.isFirstPage()"><a (click)="p.previous()"><span uk-pagination-previous></span></a></li>
<li *ngFor="let page of p.pages" [class.uk-active]="p.getCurrent() === page.value">
<a (click)="p.setCurrent(page.value)" *ngIf="p.getCurrent() !== page.value">
<span>{{ page.label }}</span>
</a>
<span *ngIf="p.getCurrent() === page.value">{{ page.label }}</span>
</li>
<li [class.uk-disabled]="p.isLastPage()"><a (click)="p.next()"><span uk-pagination-next></span></a></li>
</ul>
</pagination-template>
</div>
</div>
</div>
<div class="uk-section uk-section-default">
<div class="uk-container uk-container-expand">
<h4>Your mining profiles <span class="cm-tooltip" uk-icon="icon: info" title="Each <b>mining profile</b> consists of the data and the rules used to define a <b>mining procedure</b>.<br>Click the profile to <b>edit</b>." uk-tooltip="pos: right"></span></h4>
<h4>My mining profiles <span class="cm-tooltip" uk-icon="icon: info" title="Each <b>mining profile</b> consists of the data and the rules used to define a <b>mining procedure</b>.<br>Click the profile to <b>edit</b>." uk-tooltip="pos: right"></span></h4>
<!--<div uk-grid>-->
<!--<div class="uk-width-expand@m">-->
<div class="uk-overflow-auto">

View File

@ -5,6 +5,7 @@ import UIkit from 'uikit';
import {PaginationInstance} from 'ngx-pagination';
import {ProfileMetadata} from './profile-metadata';
import {ExampleProfilesMetadata} from './example-profiles-metadata';
import {UsersMetadata} from './users-metadata';
import {saveFile} from '../util';
@Component({
@ -16,6 +17,14 @@ export class ManageprofilesComponent implements OnInit {
// TODO profile table sorting: https://ciphertrick.com/2017/08/01/search-sort-pagination-in-angular/
public allUsersProfiles: Array<UsersMetadata> = [];
public statusValues = [
'Saved',
'Evaluating',
'On Beta'
];
public isCommunityManager = false;
public userSavedProfiles: Array<ProfileMetadata> = [];
public exampleProfiles: Array<ExampleProfilesMetadata> = [];
@ -29,17 +38,70 @@ export class ManageprofilesComponent implements OnInit {
}
ngOnInit() {
this.initialServerhandshake();
this.route.queryParams
.subscribe(
params => {
console.log('queryParams', params['communityId']);
this.initialServerhandshake(params['communityId']);
});
this.isCommunityManager = this.manageProfilesService.isCommunityManager === 'true';
}
initialServerhandshake(): void {
this.manageProfilesService.initialServerHandshake()
initialServerhandshake(communityId: string): void {
this.manageProfilesService.initialServerHandshake(communityId)
.subscribe(() => {
if (this.isCommunityManager) {
this.getAllUsersProfiles();
}
this.getSavedProfiles();
this.getExampleProfiles();
});
}
getAllUsersProfiles(): void {
this.manageProfilesService.getUsersProfiles()
.subscribe(res => {
if (res) {
this.allUsersProfiles = res;
}
});
}
loadUserProfileAdmin(userId: string, profileId: string, name: string): void {
this.manageProfilesService.loadUserProfileAdmin(userId, profileId)
.subscribe(res => {
// clear localstorage values
this.clearLocalStorage();
// store to client all profile data
localStorage.setItem('docname', res.docname);
localStorage.setItem('docsnumber', res.docsnumber);
localStorage.setItem('concepts', res.concepts);
localStorage.setItem('poswords', JSON.stringify(res.poswords));
localStorage.setItem('negwords', JSON.stringify(res.negwords));
localStorage.setItem('contextprev', res.contextprev);
localStorage.setItem('contextmiddle', res.contextmiddle);
localStorage.setItem('contextnext', res.contextnext);
localStorage.setItem('wordssplitnum', res.wordssplitnum);
localStorage.setItem('punctuation', res.punctuation);
localStorage.setItem('stopwords', res.stopwords);
localStorage.setItem('lowercase', res.lowercase);
localStorage.setItem('stemming', res.stemming);
this.router.navigate(['../upload-content'], {relativeTo: this.route, queryParamsHandling: 'preserve'});
});
}
downloadUserProfileAdmin(userId: string, profileId: string, profileName: string): void {
this.manageProfilesService.downloadUserProfileAdmin(userId, profileId)
.subscribe(res => {
saveFile(res, profileName.replace(/ /g, '_') + '.oamp');
});
}
onStatusChange(userId: string, profileId: string, status: string): void {
this.manageProfilesService.updateProfileStatus(userId, profileId, status)
.subscribe();
}
getSavedProfiles(): void {
this.manageProfilesService.getSavedProfiles()
.subscribe(res => {

View File

@ -5,6 +5,7 @@ import {Util} from '../util';
import {Observable} from 'rxjs/Observable';
import {ProfileMetadata} from './profile-metadata';
import {ExampleProfilesMetadata} from './example-profiles-metadata';
import {UsersMetadata} from './users-metadata';
@Injectable()
export class ManageprofilesService {
@ -13,8 +14,11 @@ export class ManageprofilesService {
private userId = '';
private backendServerAddress = '';
public isCommunityManager = 'false';
private initServerHandshake = '/initialhandshake';
private getusersProfilesUrl = '/getusersprofiles';
private updateProfileStatusUrl = '/updateprofilestatus';
private getSavedProfilesUrl = '/getuserprofiles';
private downloadProfileUrl = '/downloadprofile';
private DeleteuserProfileUrl = '/deleteuserprofile';
@ -27,10 +31,34 @@ export class ManageprofilesService {
constructor(private http: HttpClient) {
this.userId = this.util.getUserId();
this.backendServerAddress = this.util.getBackendServerAddress();
this.isCommunityManager = this.util.getIsCommunityManager();
}
initialServerHandshake(): Observable<any> {
return this.http.get(this.backendServerAddress + this.initServerHandshake + `?user=${this.userId}`)
initialServerHandshake(communityId: string): Observable<any> {
return this.http.get(this.backendServerAddress + this.initServerHandshake + `?user=${this.userId}&communityId=${communityId}`)
.catch(this.util.handleError);
}
getUsersProfiles(): Observable<UsersMetadata[]> {
return this.http.get(this.backendServerAddress + this.getusersProfilesUrl + `?isinadministrators=${this.isCommunityManager}`)
.map(data => data['profiles'])
.catch(this.util.handleError);
}
updateProfileStatus(userId: string, profileId: string, status: string): Observable<any> {
return this.http.post(this.backendServerAddress + this.updateProfileStatusUrl, {isinadministrators: this.isCommunityManager, user: userId, id: profileId, status: status})
.catch(this.util.handleError);
}
downloadUserProfileAdmin(userId: string, profileId: string): Observable<any> {
return this.http.post(this.backendServerAddress + this.downloadProfileUrl,
{user: userId, id: profileId}, {responseType: 'blob'})
.catch(this.util.handleError);
}
loadUserProfileAdmin(userId: string, profileId: string): Observable<ProfileData> {
return this.http.post<ProfileData>(this.backendServerAddress + this.loadSavedProfileUrl, {user: userId, id: profileId})
.catch(this.util.handleError);
}

View File

@ -0,0 +1,9 @@
export class UsersMetadata {
user: string;
userId: string;
profile: string;
profileId: string;
datecreated: string;
status: string;
}

View File

@ -23,10 +23,12 @@
<!--</ul>-->
<!--</div>-->
<!--</div>-->
<div class="uk-alert uk-alert-primary">
<div><span class="uk-margin-small-right uk-icon" uk-icon="warning"></span>
This functionality is not yet fully integrated, stay tuned!
</div>
<!--TODO https://dribbble.com/shots/139895-Checkout-progress-bar-r-2-->
<!--TODO https://codetea.com/material-design-breadcrumb-progress-tracker/-->
</div>
<div *ngIf="proccessStep>0" class="uk-section uk-section-default" style="padding-bottom: 50px;">
<div class="uk-container uk-container-large">
<div class="uk-grid-collapse uk-child-width-expand" uk-grid>

View File

@ -1,9 +1,9 @@
import {Observable} from 'rxjs/Observable';
import UIkit from 'uikit';
import {HttpErrorResponse} from '@angular/common/http';
import { saveAs } from 'file-saver/FileSaver';
import { Response } from '@angular/http';
import {ErrorObservable} from 'rxjs/observable/ErrorObservable';
import {Observable} from 'rxjs';
export class Util {
@ -30,6 +30,10 @@ export class Util {
public getBackendServerAddress(): string {
return localStorage.getItem('mining_backend_address');
}
public getIsCommunityManager(): string {
return localStorage.getItem('isCommunityManager');
}
}
/**

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>BETA Interactive Minin</title>
<title>BETA Interactive Mining</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">

View File

@ -45,6 +45,8 @@ class Application(tornado.web.Application):
handlers = [
(r"/version", VersionHandler),
(r"/initialhandshake", InitialClientHandshakeHandler),
(r"/getusersprofiles", GetUsersProfilesHandler),
(r"/updateprofilestatus", UpdateProfileStatusHandler),
(r"/getuserprofiles", GetUserProfilesHandler),
(r"/loaduserprofile", LoadUserProfileHandler),
(r"/deleteuserprofile", DeleteUserProfileHandler),
@ -381,19 +383,33 @@ class InitialClientHandshakeHandler(BaseHandler):
if 'user' in self.request.arguments and self.request.arguments['user'][0] != '':
user_id = self.request.arguments['user'][0]
database_file_name = "users_files/OAMiningProfilesDatabase_{0}.db".format(user_id)
if 'communityId' not in self.request.arguments or self.request.arguments['communityId'][0] == '':
self.set_status(400)
self.write("Missing arguement community id.")
return
community_id = self.request.arguments['communityId'][0]
import sys
sys.path.append(msettings.MADIS_PATH)
import madis
if (not os.path.isfile(database_file_name)):
if not os.path.exists("users_files"):
os.makedirs(directory)
os.makedirs("users_files")
# create a database where the user stores his profiles info
import sys
sys.path.append(msettings.MADIS_PATH)
import madis
# get the database cursor
cursor=madis.functions.Connection(database_file_name).cursor()
# Create database table
cursor.execute("drop table if exists community", parse=False)
cursor.execute("create table community(id)", parse=False)
cursor.execute('INSERT INTO community VALUES("{0}")'.format(community_id), parse=False)
cursor.execute("drop table if exists database", parse=False)
cursor.execute("create table database(id,name,datecreated,status,matches,docname,docsnumber)", parse=False)
cursor.close()
else:
cursor=madis.functions.Connection(database_file_name).cursor()
cursor.execute("drop table if exists community", parse=False)
cursor.execute("create table community(id)", parse=False)
cursor.execute('INSERT INTO community VALUES("{0}")'.format(community_id), parse=False)
cursor.close()
else:
self.set_status(400)
self.write("Missing cookie containing user's id...")
@ -408,6 +424,106 @@ class InitialClientHandshakeHandler(BaseHandler):
return
class GetUsersProfilesHandler(BaseHandler):
passwordless=True
def set_default_headers(self):
self.set_header("Access-Control-Allow-Origin", "*")
self.set_header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
self.set_header('Access-Control-Allow-Methods', 'GET, OPTIONS')
self.set_header('Access-Control-Allow-Credentials', 'true')
self.set_header('Content-Type', 'application/json')
def options(self):
# no body
self.set_status(204)
self.finish()
def get(self):
try:
# Check if the user has the admin parameter
if 'isinadministrators' not in self.request.arguments or self.request.arguments['isinadministrators'][0] != 'true':
self.set_status(400)
self.write("Must be an admin")
return
# list users
users = [re.search('OAMiningProfilesDatabase_([w0-9]+).+', f).group(1) for f in os.listdir('./users_files') if re.match(r'OAMiningProfilesDatabase_[w0-9]+\.db', f)]
# for every user, read its database to find his profiles
import sys
sys.path.append(msettings.MADIS_PATH)
import madis
# data to be sent
data = {}
users_profiles = []
for user in users:
database_file_name = "users_files/OAMiningProfilesDatabase_{0}.db".format(user)
if not os.path.isfile(database_file_name):
self.set_status(400)
self.write("Missing user\'s database")
return
# get the database cursor
cursor=madis.functions.Connection(database_file_name).cursor()
try:
# get community id
community_id = [r for r in cursor.execute("SELECT id FROM community")][0]
except Exception as ints:
print ints
community_id = 'Unkown '+user
for r in cursor.execute("SELECT id,name,datecreated,status,matches,docname FROM database order by rowid desc"):
users_profiles.append({"user":community_id,"userId":user,"profileId":r[0], "profile": r[1], "datecreated": r[2], "status": r[3], "matches": r[4], "docname": r[5]})
data['profiles'] = users_profiles
self.write(json.dumps(data))
self.finish()
except Exception as ints:
self.set_status(400)
self.write("A server error occurred, please contact administrator!")
self.finish()
print ints
return
class UpdateProfileStatusHandler(BaseHandler):
passwordless=True
def set_default_headers(self):
self.set_header("Access-Control-Allow-Origin", "*")
self.set_header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
self.set_header('Access-Control-Allow-Methods', 'POST, OPTIONS')
self.set_header('Access-Control-Allow-Credentials', 'true')
self.set_header('Content-Type', 'application/json')
def options(self):
# no body
self.set_status(204)
self.finish()
def post(self):
try:
# get user id from body. Must have
request_arguments = json.loads(self.request.body)
if 'isinadministrators' not in request_arguments or request_arguments['isinadministrators'] != 'true':
self.set_status(400)
self.write("Must be an admin")
return
import sys
sys.path.append(msettings.MADIS_PATH)
import madis
user = request_arguments['user']
profile_id = request_arguments['id']
database_file_name = "users_files/OAMiningProfilesDatabase_{0}.db".format(user)
if not os.path.isfile(database_file_name):
self.set_status(400)
self.write("Missing user\'s database")
return
cursor=madis.functions.Connection(database_file_name).cursor()
# Write new Profile status to users database
status = request_arguments['status']
cursor.execute('UPDATE database set status="{1}" where id="{0}"'.format(profile_id,status), parse=False)
cursor.close()
self.write(json.dumps({}))
self.finish()
except Exception as ints:
self.set_status(400)
self.write("A server error occurred, please contact administrator!")
self.finish()
print ints
return
class GetUserProfilesHandler(BaseHandler):
passwordless=True
def set_default_headers(self):
@ -445,7 +561,7 @@ class GetUserProfilesHandler(BaseHandler):
user_profiles = []
for r in cursor.execute("SELECT id,name,datecreated,status,matches,docname FROM database order by rowid desc"):
user_profiles.append({"id":r[0], "name": r[1], "datecreated": r[2], "status": r[3], "matches": r[4], "docname": r[5]})
data['profiles'] = user_profiles
data['profiles'] = user_profiles
cursor.close()
self.write(json.dumps(data))
self.finish()

View File

Binary file not shown.