Commit 67f1def1 authored by Markus Opolka's avatar Markus Opolka
Browse files

Merge branch 'v1.1.5' into 'master'

V1.1.5

Closes #17 and #15

See merge request !9
parents 5e6b3b73 04c5bb08
......@@ -177,12 +177,18 @@ app.get('/api/search/:letter?', function (req, res, next) {
res.send(data)
})
app.get('/api/glossary/features', function (req, res) {
// Feature Glossary
res.send(lib.glossary(loadDocuments(DIR)))
})
app.get('/api/features/:letter?', function (req, res) {
// Feature Search Endpoint with query parameters
// <feature category="diakritika" type="akut" subtype="akutstattgravis" ref="26">
if (!req.query.category){
res.send({})
return next('No Query provided')
if (!req.query) {
res.status(400).send('No Query provided')
return
}
let query = {
......@@ -202,6 +208,11 @@ app.get('/api/features/:letter?', function (req, res) {
for (let doc of documents) {
let obj = loadDocument(doc)
if (!obj) {
continue
}
if (obj.valid) {
let results = lib.features(obj, query)
if (results !== null) {
......@@ -213,6 +224,7 @@ app.get('/api/features/:letter?', function (req, res) {
res.send(data.sort(lib.compare))
})
app.get('/api/letters/:letter?', function (req, res) {
// Document Endpoint with optional Document name
// Lists either all or one given document
......@@ -242,6 +254,10 @@ app.get('/api/metadata/reload', function (req, res) {
// Loading all documents to cache
loadDocumentsToCache(DIR)
// Loading all documents to cache
// loadGlossaryToCache(DIR)
// Where the magic happens
app.listen(PORT, function () {
console.log('> Listening at http://localhost:' + PORT)
......
......@@ -143,6 +143,76 @@ function searchFeaturesInDocument (document, query) {
return document
}
function featureToString (feature) {
/*
* Turn into feature object into category>type>subtype String
*/
let category = feature.category
let type = feature.type
let subtype = feature.subtype
let ret = ''
if (category !== undefined) {
ret = ret.concat(category)
}
if (type !== undefined) {
ret = ret.concat(' > ', type)
}
if (subtype !== undefined) {
ret = ret.concat(' > ', subtype)
}
return ret
}
function featureGlossary (objs) {
/*
* Turn list of documents objects into a glossary set
*/
let featureList = []
for (let document of objs) {
try {
let documentFeatures = findKeyRecursive(document, 'feature')
for (let feature of documentFeatures) {
delete feature._attributes['ref']
featureList.push(feature._attributes)
}
} catch (err) {
console.log(arguments.callee) // eslint-disable-line no-caller
console.log('>> Error while getting features from' + document.name)
console.log(err)
}
}
let categories = []
let types = []
let subtypes = []
for (let feat of featureList) {
if (feat.category !== undefined) {
categories.push(feat.category)
}
if (feat.type !== undefined) {
types.push(feat.type)
}
if (feat.subtype !== undefined) {
subtypes.push(feat.subtype)
}
}
let ret = {
categories: Array.from(new Set(categories)),
types: Array.from(new Set(types)),
subtypes: Array.from(new Set(subtypes))
}
return ret
}
function metadataTable (objs) {
/*
* Turn list of documents objects into metadata table format
......@@ -189,6 +259,9 @@ module.exports = {
table: function (objs) {
return metadataTable(objs)
},
glossary: function (objs) {
return featureGlossary(objs)
},
compare: function (a, b) {
if (a.hits > b.hits) { return -1 }
if (a.hits < b.hits) { return 1 }
......
......@@ -61,19 +61,19 @@
icon: 'home'
}, {
href: '/letters',
title: 'Letters',
title: 'Lettres',
icon: 'mail_outline'
}, {
href: '/metadata',
title: 'Metadata',
title: 'Métadonnées',
icon: 'apps'
}, {
href: '/features',
title: 'Features',
title: 'Caractéristiques',
icon: 'menu'
}, {
href: '/search',
title: 'Search',
title: 'Recherche',
icon: 'search'
}]
}
......
......@@ -5,6 +5,19 @@
<h3>{{header}}</h3>
</v-flex>
<v-flex xs12>
<p>
les caractéristiques sont les propriétés de chaque lettre. Elles disposent d'une catégorie, d'un type et d'un sous-type organisés de manière hierarchique.
</p>
<p>
La 'Recherche de caractéristique' facilite la recherche rapipde de toute sorte de traits propres aux lettres.
La 'Recherche de caractéristique' soutient également les expressions régulières et peut être restreinte à une seule lettre.
</p>
</v-flex>
<!-- Select Letter -->
<v-flex xs12>
<v-select
......@@ -12,40 +25,43 @@
v-model="selected"
label="Select"
single-line
bottom
prepend-icon="local_post_office"
></v-select>
</v-flex>
<!-- Input Fields for Search -->
<v-flex xs12 md3>
<v-text-field
<v-autocomplete
v-model="feature_category"
type="text" label="Category"
@keyup.enter.native="validate">
</v-text-field>
:items="feature_categories_glossary"
label="Category"
@keyup.enter.native="validate"
>
</v-autocomplete>
</v-flex>
<v-flex xs12 md3>
<v-text-field
<v-autocomplete
v-model="feature_type"
type="text"
label="Type"
@keyup.enter.native="validate">
</v-text-field>
:items="feature_types_glossary"
label="Types"
@keyup.enter.native="validate"
>
</v-autocomplete>
</v-flex>
<v-flex xs12 md3>
<v-text-field
<v-autocomplete
v-model="feature_subtype"
type="text"
label="Subtype"
@keyup.enter.native="validate">
</v-text-field>
:items="feature_subtypes_glossary"
label="Subtypes"
@keyup.enter.native="validate"
>
</v-autocomplete>
</v-flex>
<!-- Search Buttons -->
<v-flex xs12 md3>
<v-btn @click="validate" color="blue-grey darken-2" class="white--text">Search</v-btn>
<v-btn @click="clear" color="blue-grey darken-2" class="white--text">Clear</v-btn>
<v-btn @click="validate" color="blue-grey darken-2" class="white--text">Rechercher</v-btn>
<v-btn @click="clear" color="blue-grey darken-2" class="white--text">Supprimer</v-btn>
</v-flex>
<!-- Invalid Search Warning -->
......@@ -64,7 +80,7 @@
<v-flex xs12 v-if="results">
<v-card color="blue-grey lighten-1" class="white--text">
<v-card-text>
Results: {{results.length}} letter(s) - {{countedHits}} hit(s)
Lettre(s): {{results.length}} dont résultat(s): {{countedHits}}
</v-card-text>
</v-card>
</v-flex>
......@@ -83,35 +99,37 @@ export default {
data () {
// Search for Features in Letters
return {
header: 'Feature Search',
header: 'Recherche de caractéristiques',
invalid: false,
searching: false,
feature_categories_glossary: [],
feature_types_glossary: [],
feature_subtypes_glossary: [],
feature_category: '',
feature_type: '',
feature_subtype: '',
results: null,
letters: [
{ text: 'All' }
{ text: 'Toutes' }
],
selected: { text: 'All' }
selected: 'Toutes'
}
},
methods: {
clear () {
// Clears the search input fields
this.feature_category = null
this.feature_type = null
this.feature_subtype = null
this.feature_category = ''
this.feature_type = ''
this.feature_subtype = ''
},
find () {
// Call feature search API with parameters
this.searching = true
let url = 'http://localhost:3000/api/features/'
// TODO: this is a bit silly
// Adding the lettername to the API endpoint
if (this.selected.text !== 'All') {
url = url + this.selected.text.replace(/ /g, '_') + '/'
if (this.selected !== 'Toutes') {
url = url + this.selected
}
let params = {
......@@ -149,10 +167,19 @@ export default {
}
},
created () {
// Get feature glossary
this.$http.get('http://localhost:3000/api/glossary/features').then(function (data) {
this.feature_categories_glossary = data.body.categories
this.feature_types_glossary = data.body.types
this.feature_subtypes_glossary = data.body.subtypes
})
// Create list of all letters
this.$http.get('http://localhost:3000/api/metadata/table').then(function (data) {
for (let letter of data.body) {
this.letters.push({text: letter.name})
if (letter.valid) {
this.letters.push({text: letter.title})
}
}
})
}
......
......@@ -15,7 +15,6 @@
</v-flex>
<v-flex xs12>
<p>Ce projet des <i>pétitions des bagnards et leurs proches</i>, commencé en février 2016, réunit des textes des personnes dites ‘peu-lettrés’ réalisés entre 1854 et 1896. Ces correspondances font preuve d’un écartement de la norme du français standard dans maints domaines: relations graphie-phonie, morphosyntaxe, lexique ou traditions discursives.</p>
<p>Le corpus, composé de textes – jusqu’ici – inconnus de la recherche linguistique, provient des <i>Archives Nationales d’outre-mer</i> à Aix-en-Provence et comprend plus de 300 documents. Dans ces lettres, les auteurs écrivent au Ministre de la Marine et des Colonies, au Préfet ou bien au Directeur afin de leur demander leur aide. Les suppliques englobent <i>grosso modo</i> cinq thèmes:</p>
......
......@@ -39,10 +39,16 @@
<v-flex xs5>
<v-card>
<v-card-text>
<v-checkbox label="Show Comments" v-model="showComments"></v-checkbox>
<v-checkbox label="Montrer commentaires" v-model="showComments"></v-checkbox>
<ul style="list-style-type:none;" class="letter-text">
<li v-for="(value, key) in letter.text.body.l" :class="value._attributes.no" v-if="hasText(formatText(value._text))">
{{value._attributes.no }}: {{ formatText(value._text) }}
<div class="teal--text" v-if="value.note && showComments">
<div v-for="note in value.note">
<span v-if="note._attributes">{{note._text}}: {{note._attributes.text}}</span>
<span v-else>{{note.text}}</span>
</div>
</div>
</li>
</ul>
</v-card-text>
......@@ -123,15 +129,17 @@ export default {
}
// So we can iterate in the template
this.features.push({text: 'Material and Visuals', root: data.body.TEI.teiHeader.xenoData.paratext})
this.features.push({text: 'Graphemics', root: data.body.TEI.teiHeader.xenoData.sprachliche_ebene.graphische_charaktersitika})
this.features.push({text: 'Lexical', root: data.body.TEI.teiHeader.xenoData.sprachliche_ebene.lexikalische_charaktersitika})
this.features.push({text: 'Morphosyntactics', root: data.body.TEI.teiHeader.xenoData.sprachliche_ebene.morphosyntaktische_charakterisitka})
this.features.push({text: 'Pragmatics', root: data.body.TEI.teiHeader.xenoData.sprachliche_ebene.textstrukturelle_pragmatische_charakterisitka})
this.features.push({text: 'Discourse', root: data.body.TEI.teiHeader.xenoData.sprachliche_ebene.diskurstraditionelle_ebene})
this.features.push({text: 'caractéristiques visuelles', root: data.body.TEI.teiHeader.xenoData.paratext})
this.features.push({text: 'caractéristiques graphiques', root: data.body.TEI.teiHeader.xenoData.sprachliche_ebene.graphische_charaktersitika})
this.features.push({text: 'caractéristiques lexicales', root: data.body.TEI.teiHeader.xenoData.sprachliche_ebene.lexikalische_charaktersitika})
this.features.push({text: 'caractéristiques morphosyntaxiques', root: data.body.TEI.teiHeader.xenoData.sprachliche_ebene.morphosyntaktische_charakterisitka})
this.features.push({text: 'caractéristiques pragmatiques', root: data.body.TEI.teiHeader.xenoData.sprachliche_ebene.textstrukturelle_pragmatische_charakterisitka})
this.features.push({text: 'caractéristiques de tradition discursive', root: data.body.TEI.teiHeader.xenoData.sprachliche_ebene.diskurstraditionelle_ebene})
// Do this last for progress bar
this.letter = data.body.TEI
console.log(data.body.TEI.text.body.l[0].note)
})
}
}
......
......@@ -56,7 +56,7 @@ export default {
name: 'Letters',
data () {
return {
header: 'Letters',
header: 'Lettres',
letters: null,
reloading: false,
timeout: 1000,
......
......@@ -9,7 +9,7 @@
<v-card-title>
<v-text-field
append-icon="search"
label="Search"
label="Recherche"
single-line
hide-details
v-model="search"
......@@ -64,7 +64,7 @@ export default {
data () {
// Metadata Overview in Letters
return {
header: 'Metadata',
header: 'Métadonnées',
max25chars: (v) => v.length <= 25 || 'Input too long!',
tmp: '',
search: '',
......
......@@ -4,7 +4,7 @@
<span class="title">{{letter.name}}</span><v-chip label color="lime accent-4">{{letter.collection}}</v-chip>
<v-chip color="indigo" text-color="white" v-if="letter.hits">
<v-avatar class="indigo darken-4">{{letter.hits}}</v-avatar>
Hits
résultat(s)
</v-chip>
</v-card-title>
<v-card-text>
......@@ -13,7 +13,7 @@
<v-chip outline small color="secondary"> {{hit._text}} </v-chip>
<v-chip label small v-if="has(hit, '_attributes')">
<span v-if="has(hit._attributes, 'no')" >Line: {{(hit._attributes.no)}}</span>
<span v-if="has(hit._attributes, 'no')" >Ligne: {{(hit._attributes.no)}}</span>
<span v-if="has(hit._attributes, 'category')" >Category: {{(hit._attributes.category)}}</span>
<span v-if="has(hit._attributes, 'type')" >, Type: {{(hit._attributes.type)}}</span>
<span v-if="has(hit._attributes, 'subtype')" >, Subtype: {{(hit._attributes.subtype)}}</span>
......@@ -30,7 +30,7 @@
</ul>
</v-card-text>
<v-card-actions>
<v-btn :to="letter.link" flat>View</v-btn>
<v-btn :to="letter.link" flat>Montrer</v-btn>
</v-card-actions>
</v-card>
</template>
......
......@@ -5,28 +5,20 @@
<h3>{{header}}</h3>
</v-flex>
<!-- Search Help -->
<v-flex xs12>
<v-expansion-panel>
<v-expansion-panel-content>
<div slot="header">Toggle Syntax Help</div>
<v-card>
<v-card-text class="grey lighten-3">
<p>Content in an element: <strong>element:content</strong> (Regular Expressions are supported)</p>
<p>If no element is provided, the text will be searched.</p>
<!-- <p>Attribute of an element: <strong>element@attribute=value</strong></p> -->
<!-- <p>Attribute and content: <strong>element@attribute=value:content</strong></p> -->
</v-card-text>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
<p>Ci-dessous, il est possible de rechercher toute sorte de tag et de co-occurrence graphique à l'aide des expressions régulières.</p>
<div class="subheading">Syntaxe</div>
<p>Rechercher <strong>contenu</strong> dans un <strong>tag</strong>: <strong>tag:contenu</strong></p>
<p>Quand le tag n'est pas spécifié, le texte sert de base de recherche.</p>
</v-flex>
<!-- Main Input Field -->
<v-flex xs12 md9>
<v-text-field
v-model="search"
label="Query"
label="Entrée"
data-vv-search="search"
required
@keyup.enter.native="validate"
......@@ -35,8 +27,8 @@
<!-- Search Buttons -->
<v-flex xs12 md3>
<v-btn @click="validate" color="blue-grey darken-2" class="white--text">Search</v-btn>
<v-btn @click="clear" color="blue-grey darken-2" class="white--text">Clear</v-btn>
<v-btn @click="validate" color="blue-grey darken-2" class="white--text">Rechercher</v-btn>
<v-btn @click="clear" color="blue-grey darken-2" class="white--text">Supprimer</v-btn>
</v-flex>
<!-- Options -->
......@@ -59,7 +51,7 @@
<v-flex xs12 v-if="results">
<v-card color="blue-grey lighten-1" class="white--text">
<v-card-text>
Results: {{results.length}} letter(s)
Résultats: {{results.length}} lettre(s)
</v-card-text>
</v-card>
</v-flex>
......@@ -79,7 +71,7 @@ export default {
name: 'Search',
data () {
return {
header: 'Search',
header: 'Rechercher',
invalid: false,
search: '',
pattern: '^([a-z]+):(.+)',
......
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