mirror of
https://github.com/umap-project/umap.git
synced 2025-04-28 19:42:36 +02:00
wip: display templates in importer by origin (me/staff/community)
Co-authored-by: David Larlet <david@larlet.fr>
This commit is contained in:
parent
23f7337a98
commit
71c6974c3c
6 changed files with 85 additions and 45 deletions
|
@ -9,6 +9,13 @@ class PublicManager(models.Manager):
|
||||||
.filter(share_status=self.model.PUBLIC)
|
.filter(share_status=self.model.PUBLIC)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def starred_by_staff(self):
|
||||||
|
from .models import Star, User
|
||||||
|
|
||||||
|
staff = User.objects.filter(is_staff=True)
|
||||||
|
stars = Star.objects.filter(by__in=staff).values("map")
|
||||||
|
return self.get_queryset().filter(pk__in=stars)
|
||||||
|
|
||||||
|
|
||||||
class PrivateQuerySet(models.QuerySet):
|
class PrivateQuerySet(models.QuerySet):
|
||||||
def for_user(self, user):
|
def for_user(self, user):
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
margin-top: 100px;
|
margin-top: 100px;
|
||||||
width: var(--dialog-width);
|
width: var(--dialog-width);
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
max-height: 50vh;
|
max-height: 80vh;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border: 1px solid #222;
|
border: 1px solid #222;
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
|
@ -12,11 +12,14 @@
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
max-height: 90vh;
|
|
||||||
}
|
}
|
||||||
.umap-dialog ul + h4 {
|
.umap-dialog ul + h4 {
|
||||||
margin-top: var(--box-margin);
|
margin-top: var(--box-margin);
|
||||||
}
|
}
|
||||||
|
.umap-dialog .body {
|
||||||
|
max-height: 50vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
:where([data-component="no-dialog"]:not([hidden])) {
|
:where([data-component="no-dialog"]:not([hidden])) {
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -725,7 +725,7 @@ Fields.IconUrl = class extends Fields.BlurInput {
|
||||||
<button class="flat tab-url" data-ref=url>${translate('URL')}</button>
|
<button class="flat tab-url" data-ref=url>${translate('URL')}</button>
|
||||||
</div>
|
</div>
|
||||||
`)
|
`)
|
||||||
this.tabs.appendChild(root)
|
;[recent, symbols, chars, url].forEach((node) => this.tabs.appendChild(node))
|
||||||
if (Icon.RECENT.length) {
|
if (Icon.RECENT.length) {
|
||||||
recent.addEventListener('click', (event) => {
|
recent.addEventListener('click', (event) => {
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
|
|
@ -4,26 +4,22 @@ import { BaseAjax, SingleMixin } from '../autocomplete.js'
|
||||||
import { translate } from '../i18n.js'
|
import { translate } from '../i18n.js'
|
||||||
import * as Utils from '../utils.js'
|
import * as Utils from '../utils.js'
|
||||||
|
|
||||||
const BOUNDARY_TYPES = {
|
|
||||||
admin_6: 'département',
|
|
||||||
admin_7: 'pays (loi Voynet)',
|
|
||||||
admin_8: 'commune',
|
|
||||||
admin_9: 'quartier, hameau, arrondissement',
|
|
||||||
political: 'canton',
|
|
||||||
local_authority: 'EPCI',
|
|
||||||
}
|
|
||||||
|
|
||||||
const TEMPLATE = `
|
const TEMPLATE = `
|
||||||
<h3>${translate('Load template')}</h3>
|
<div>
|
||||||
<p>${translate('GeoDataMine: thematic data from OpenStreetMap')}.</p>
|
<h3>${translate('Load map template')}</h3>
|
||||||
<div class="formbox">
|
<p>${translate('Use a template to initialize your map')}.</p>
|
||||||
<select name="theme">
|
<div class="formbox">
|
||||||
<option value="">${translate('Choose a template')}</option>
|
<div class="flat-tabs" data-ref="tabs">
|
||||||
</select>
|
<button type="button" class="flat" data-value="mine" data-ref="mine">${translate('My templates')}</button>
|
||||||
<label>
|
<button type="button" class="flat" data-value="staff">${translate('Staff templates')}</button>
|
||||||
<input type="checkbox" name="include_data" />
|
<button type="button" class="flat" data-value="community">${translate('Community templates')}</button>
|
||||||
${translate('Include template data, if any')}
|
</div>
|
||||||
</label>
|
<div data-ref="body" class="body"></div>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="include_data" />
|
||||||
|
${translate('Include template data, if any')}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -35,28 +31,50 @@ export class Importer {
|
||||||
}
|
}
|
||||||
|
|
||||||
async open(importer) {
|
async open(importer) {
|
||||||
const container = DomUtil.create('div')
|
const [root, { tabs, include_data, body, mine }] =
|
||||||
container.innerHTML = TEMPLATE
|
Utils.loadTemplateWithRefs(TEMPLATE)
|
||||||
const select = container.querySelector('select')
|
|
||||||
const uri = this.umap.urls.get('template_list')
|
const uri = this.umap.urls.get('template_list')
|
||||||
const [data, response, error] = await this.umap.server.get(uri)
|
const userIsAuth = Boolean(this.umap.properties.user?.id)
|
||||||
if (!error) {
|
const defaultTab = userIsAuth ? 'mine' : 'staff'
|
||||||
for (const template of data.templates) {
|
mine.hidden = !userIsAuth
|
||||||
DomUtil.element({
|
|
||||||
tagName: 'option',
|
const loadTemplates = async (source) => {
|
||||||
value: template.id,
|
const [data, response, error] = await this.umap.server.get(
|
||||||
textContent: template.name,
|
`${uri}?source=${source}`
|
||||||
parent: select,
|
)
|
||||||
})
|
if (!error) {
|
||||||
|
body.innerHTML = ''
|
||||||
|
for (const template of data.templates) {
|
||||||
|
const item = Utils.loadTemplate(
|
||||||
|
`<dl>
|
||||||
|
<dt><label><input type="radio" value="${template.id}" name="template" />${template.name}</label></dt>
|
||||||
|
<dd>${template.description}</dd>
|
||||||
|
</dl>`
|
||||||
|
)
|
||||||
|
body.appendChild(item)
|
||||||
|
}
|
||||||
|
tabs.querySelectorAll('button').forEach((el) => el.classList.remove('on'))
|
||||||
|
tabs.querySelector(`[data-value="${source}"]`).classList.add('on')
|
||||||
|
} else {
|
||||||
|
console.error(response)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
console.error(response)
|
|
||||||
}
|
}
|
||||||
|
loadTemplates(defaultTab)
|
||||||
|
tabs
|
||||||
|
.querySelectorAll('button')
|
||||||
|
.forEach((el) =>
|
||||||
|
el.addEventListener('click', () => loadTemplates(el.dataset.value))
|
||||||
|
)
|
||||||
const confirm = (form) => {
|
const confirm = (form) => {
|
||||||
|
console.log(form)
|
||||||
|
if (!form.template) {
|
||||||
|
Alert.error(translate('You must select a template.'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
let url = this.umap.urls.get('map_download', {
|
let url = this.umap.urls.get('map_download', {
|
||||||
map_id: select.options[select.selectedIndex].value,
|
map_id: form.template,
|
||||||
})
|
})
|
||||||
if (!container.querySelector('[name=include_data]').checked) {
|
if (!form.include_data) {
|
||||||
url = `${url}?include_data=0`
|
url = `${url}?include_data=0`
|
||||||
}
|
}
|
||||||
importer.url = url
|
importer.url = url
|
||||||
|
@ -67,7 +85,7 @@ export class Importer {
|
||||||
|
|
||||||
importer.dialog
|
importer.dialog
|
||||||
.open({
|
.open({
|
||||||
template: container,
|
template: root,
|
||||||
className: `${this.id} importer dark`,
|
className: `${this.id} importer dark`,
|
||||||
accept: translate('Use this template'),
|
accept: translate('Use this template'),
|
||||||
cancel: false,
|
cancel: false,
|
||||||
|
|
|
@ -301,6 +301,15 @@
|
||||||
</form>
|
</form>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</details>
|
</details>
|
||||||
|
<details open>
|
||||||
|
<summary>With tabs</summary>
|
||||||
|
<div class="flat-tabs" data-ref="tabs">
|
||||||
|
<button class="flat on" data-ref="recent">Récents</button>
|
||||||
|
<button class="flat" data-ref="symbols">Symbole</button>
|
||||||
|
<button class="flat" data-ref="chars">Emoji & texte</button>
|
||||||
|
<button class="flat" data-ref="url">URL</button>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
</div>
|
</div>
|
||||||
<h4>Importers</h4>
|
<h4>Importers</h4>
|
||||||
<div class="umap-dialog window importers dark">
|
<div class="umap-dialog window importers dark">
|
||||||
|
|
|
@ -138,9 +138,7 @@ class PublicMapsMixin(object):
|
||||||
return maps
|
return maps
|
||||||
|
|
||||||
def get_highlighted_maps(self):
|
def get_highlighted_maps(self):
|
||||||
staff = User.objects.filter(is_staff=True)
|
qs = Map.public.starred_by_staff()
|
||||||
stars = Star.objects.filter(by__in=staff).values("map")
|
|
||||||
qs = Map.public.filter(pk__in=stars)
|
|
||||||
maps = qs.order_by("-modified_at")
|
maps = qs.order_by("-modified_at")
|
||||||
return maps
|
return maps
|
||||||
|
|
||||||
|
@ -1459,9 +1457,14 @@ class TemplateList(ListView):
|
||||||
model = Map
|
model = Map
|
||||||
|
|
||||||
def render_to_response(self, context, **response_kwargs):
|
def render_to_response(self, context, **response_kwargs):
|
||||||
if self.request.user.is_authenticated:
|
source = self.request.GET.get("source")
|
||||||
|
if source == "mine":
|
||||||
qs = Map.private.filter(is_template=True).for_user(self.request.user)
|
qs = Map.private.filter(is_template=True).for_user(self.request.user)
|
||||||
else:
|
elif source == "community":
|
||||||
qs = Map.public.filter(is_template=True)
|
qs = Map.public.filter(is_template=True)
|
||||||
templates = [{"id": m.id, "name": m.name} for m in qs]
|
elif source == "staff":
|
||||||
|
qs = Map.public.starred_by_staff().filter(is_template=True)
|
||||||
|
templates = [
|
||||||
|
{"id": m.id, "name": m.name, "description": m.description} for m in qs
|
||||||
|
]
|
||||||
return simple_json_response(templates=templates)
|
return simple_json_response(templates=templates)
|
||||||
|
|
Loading…
Reference in a new issue