Commit 5690c1fc authored by Tobinsk's avatar Tobinsk
Browse files

Update proejct

parent 846c590c
Pipeline #9219 failed with stage
in 3 minutes and 46 seconds
VUE_APP_API_URL="http://localhost:8080"
VUE_APP_KEYCLOAK_ENABLE="false"
NODE_ENV=development
VUE_APP_API_URL="https://api.metagrid.ch"
VUE_APP_KEYCLOAK_ENABLE="true"
VUE_APP_KEYCLOAK_REALM="HistHub"
VUE_APP_KEYCLOAK_URL="https://iam.nubes.dodis.ch/auth"
VUE_APP_TEST_USER="test"
# please use a valid provider. Otherwise the matching won't work
VUE_APP_TEST_PROVIDER="bsg"
VUE_APP_TEST_PROVIDER="hallernet"
# tbd
VUE_APP_TEST_ROLES="user"
NODE_ENV=production
VUE_APP_API_URL="http://localhost:8080"
VUE_APP_KEYCLOAK_ENABLE="false"
VUE_APP_KEYCLOAK_URL="https://sso.histhub.ch/auth"
VUE_APP_KEYCLOAK_URL="https://iam.nubes.dodis.ch/auth"
VUE_APP_TEST_USER="test"
# please use a valid provider. Otherwise the matching won't work
VUE_APP_TEST_PROVIDER="archprofs"
......
{
"pluginsFile": "tests/e2e/plugins/index.js"
"pluginsFile": "tests/e2e/plugins/index.js",
"chromeWebSecurity": false
}
......@@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"serve": "vue-cli-service serve --mode development",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e --mode e2e",
......
......@@ -2,7 +2,10 @@
<b-overlay :show="loading" spinner-variant="primary" spinner-type="grow">
<div class="d-flex justify-content-between mb-4" v-if="!isNew">
<h3>{{single.name}}</h3>
<b-button size="sm" @click="showConfig = !showConfig"><b-icon icon="gear"></b-icon></b-button>
<b-button-group>
<b-button size="sm" @click="showConfig = !showConfig"><b-icon icon="gear"></b-icon></b-button>
<b-button size="sm" @click="trainMl(single.id)"><b-icon icon="gem"></b-icon></b-button>
</b-button-group>
</div>
<transition name="fade" duration="300" >
<FormContainer v-if="showConfig">
......@@ -134,7 +137,7 @@
},
methods: {
...mapActions('match', {'new': 'new', 'singleAction': 'single'}),
...mapActions('proposal', ['test']),
...mapActions('proposal', ['test', 'machineLearningTrain']),
/**
* Pre-save hook. At the end we call save
**/
......@@ -177,6 +180,12 @@
}
)
},
/**
* Train the ml with the submitted data
*/
trainMl(id){
this.machineLearningTrain(id)
},
/**
* Validate a field
* @param name {string}
......
......@@ -8,6 +8,7 @@
<a :href="person.url"><b-icon-box-arrow-up-right scale="1.5"></b-icon-box-arrow-up-right></a>
</div>
<div class="provider">{{person.provider}}</div>
<div class="ml" :class="{'match': person.ml_match}"></div>
</div>
</template>
......@@ -37,5 +38,15 @@ export default {
.provider {
width: 15%;
}
.ml{
&.match {
background: green;
}
background: orange;
width: 2rem;
margin-right: 2rem;
}
}
</style>
......@@ -41,6 +41,8 @@
<div class="d-flex justify-content-end list-group-item action-footer">
<b-btn-group>
<b-button @click="preSave(ml)">Save</b-button>
<b-button @click="train(ml)">Train</b-button>
<b-button @click="predict(ml)">Predict</b-button>
</b-btn-group>
</div>
</div>
......@@ -68,6 +70,8 @@
...mapActions('concordance', ['update', 'merge']),
...mapMutations('concordance', ['edit']),
...mapMutations('proposal', ['remove']),
...mapActions('proposal', ['machineLearning', 'machineLearningPredict']),
preSave(proposal) {
// merge concordances
const matches = proposal.proposals.filter((c) => c.match);
......@@ -91,6 +95,15 @@
}
this.remove(proposal);
},
train(proposal) {
proposal.id = "test1";
this.machineLearning(proposal)
this.remove(proposal);
},
async predict(proposal) {
proposal.id = "test1";
await this.machineLearningPredict(proposal)
},
changeProposal(proposal, $event) {
proposal.persons.forEach((p) => {
p.match = $event;
......
......@@ -16,10 +16,12 @@ Vue.use(Vuelidate)
Vue.config.productionTip = false;
// in local dev we don't want to force a login. We will set the auth headers ourself in the fetch-interceptor
let keycloakLogin = 'check-sso'
let keycloakLogin = 'check-sso';
if (process.env.VUE_APP_KEYCLOAK_ENABLE === "true") {
keycloakLogin = 'login-required';
}
// eslint-disable-next-line
console.log(keycloakLogin)
Vue.use(VueKeycloakJs, {
init: {
onLoad: keycloakLogin,
......
......@@ -21,7 +21,7 @@ import {
ButtonGroupPlugin,
CardPlugin,
NavbarPlugin,
AlertPlugin
AlertPlugin, BIconGem
} from 'bootstrap-vue'
// load icons
......@@ -43,6 +43,7 @@ vue.component('BIconPlay', BIconPlay)
vue.component('BIconCalculator', BIconCalculator)
vue.component('BIconPlus', BIconPlus)
vue.component('BIconBox', BIconBox)
vue.component('BIconGem', BIconGem)
// components
vue.use(FormPlugin)
vue.use(FormGroupPlugin)
......
......@@ -86,12 +86,24 @@ export interface Match {
parameters: MatchParameter[];
}
// proposals interface
// Simple match proposal interface
export interface MatchProposal {
base: Concordance;
proposals: MatchSelection[];
}
// ml predict request data
export interface MatchPrediction {
base: Concordance;
proposals: Concordance[];
}
// Match selection interface
export interface MatchSelection extends Concordance{
match: boolean
ml_match: boolean
}
// metagridError interface for global error handling
export interface MetagridError {
title: string;
......
import {api, MatchProposal, Match, MetagridError} from '@/store';
import {api, MatchProposal, Match, MetagridError, Concordance, MatchPrediction} from '@/store';
import { Module} from "vuex"
import {Actions, Getters, Mutations} from '@/store/proposal/type';
import {ErrorType} from '@/store/error';
......@@ -33,6 +33,16 @@ const proposal: Module<ProposalState, any> = {
state.list = list;
},
[Mutations.SET_PREDICTION]: (state, prediction) => {
state.list = state.list.map((d) => {
if(d.base.id === prediction.base.id) {
console.log(prediction);
return prediction
}
return d;
})
},
/**
* Clear a list of proposals
* @param state
......@@ -173,6 +183,105 @@ const proposal: Module<ProposalState, any> = {
commit(Mutations.LIST, proposals.proposals);
commit(Mutations.FINISH_LOAD);
},
/**
* Submit new data for training the ml model
* @param commit
* @param state
* @param toPredict
*/
async [Actions.MACHINE_LEARNING]({commit, state}, toPredict: MatchPrediction, ) {
await fetch(`http://127.0.0.1:5000/traindata/${state.id}`,
{
method: 'POST',
body: JSON.stringify(toPredict),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
})
.then(r => {
if (r.status >= 200 && r.status <= 299) {
return r.json();
} else {
throw Error(r.statusText);
}
})
.catch((err) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t test the matching.',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw err;
});
},
/**
* Predict data with the trained ml
* @param commit
* @param state
* @param matchProposal
*/
async [Actions.MACHINE_LEARNING_PREDICT]({commit, state}, matchProposal: MatchProposal, ) {
const prediction = await fetch(`http://127.0.0.1:5000/predict/${state.id}`,
{
method: 'POST',
body: JSON.stringify(matchProposal),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
})
.then(r => {
if (r.status >= 200 && r.status <= 299) {
return r.json();
} else {
throw Error(r.statusText);
}
})
.catch((err) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t test the matching.',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw err;
});
commit(Mutations.SET_PREDICTION, prediction)
},
/**
* Train a ml model with the submitted data
* @param commit
* @param state
* @param matchProposal
*/
async [Actions.MACHINE_LEARNING_TRAIN]({commit, state}, matchProposal: MatchProposal, ) {
await fetch(`http://127.0.0.1:5000/train/${state.id}`,
{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
})
.then(r => {
if (r.status >= 200 && r.status <= 299) {
return r.json();
} else {
throw Error(r.statusText);
}
})
.catch((err) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t test the matching.',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw err;
});
},
}
};
......
......@@ -3,6 +3,9 @@ export const Actions = {
TEST: 'test',
ACCEPT: 'accept',
REJECT: 'reject',
MACHINE_LEARNING: 'machineLearning',
MACHINE_LEARNING_PREDICT: 'machineLearningPredict',
MACHINE_LEARNING_TRAIN: 'machineLearningTrain'
};
export const Getters = {
......@@ -17,4 +20,5 @@ export const Mutations = {
ID: 'id',
CLEAR: 'clear',
REMOVE: 'remove',
SET_PREDICTION: 'setPrediction',
};
describe('Test editing of a concordance', function () {
beforeEach(function () {
// set default user in the headers
cy.server({
headers: {
'X-Auth-Username': 'test',
'X-Auth-Provider': 'dodis',
'X-Auth-Roles': 'user',
}
cy.intercept("*", (req) => {
req.headers['X-Auth-Username'] = 'test';
req.headers['X-Auth-Provider'] = 'dodis';
req.headers['X-Auth-Roles'] = 'user';
});
// check the server
cy.server()
cy.route('GET', 'http://localhost:8080/v3/concordances/search?query=Galileo Galilei&length=1&provider=&year1=-1&year2=-1&from=0&size=20').as('search')
cy.intercept('GET', 'http://localhost:8080/v3/concordances/search?query=Galileo%20Galilei&length=1&provider=&year1=-1&year2=-1&from=0&size=20').as('search')
// visit site
cy.visit('http://localhost:3000');
// trigger search
......
......@@ -5,6 +5,6 @@ module.exports = {
https: false
},
configureWebpack: {
devtool: 'source-map'
devtool: 'eval-source-map'
}
};
......@@ -3449,14 +3449,9 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"
 
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001173:
version "1.0.30001178"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001178.tgz#3ad813b2b2c7d585b0be0a2440e1e233c6eabdbc"
integrity sha512-VtdZLC0vsXykKni8Uztx45xynytOi71Ufx9T8kHptSw9AL4dpqailUJJHavttuzUe1KYuBYtChiWv+BAb7mPmQ==
caniuse-lite@^1.0.30001297, caniuse-lite@^1.0.30001312:
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001173, caniuse-lite@^1.0.30001297, caniuse-lite@^1.0.30001312:
version "1.0.30001312"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz"
integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==
 
capture-stack-trace@^1.0.0:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment