]> git.ipfire.org Git - ipfire.org.git/commitdiff
Refactor mirrors
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 26 Oct 2018 18:58:04 +0000 (19:58 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 26 Oct 2018 18:58:04 +0000 (19:58 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
16 files changed:
.gitmodules
Makefile.am
src/backend/mirrors.py
src/flag-icons [new submodule]
src/scss/_icons.scss
src/scss/style.scss
src/templates/mirrors-item.html [deleted file]
src/templates/mirrors.html [deleted file]
src/templates/mirrors/index.html [new file with mode: 0644]
src/templates/mirrors/mirror.html [new file with mode: 0644]
src/templates/modules/mirrors-table.html [deleted file]
src/web/__init__.py
src/web/handlers.py
src/web/handlers_mirrors.py [deleted file]
src/web/mirrors.py [new file with mode: 0644]
src/web/ui_modules.py

index 72ae9d48dc601c4e85d708e54f7a59a086c6a2c8..2933dfd534822b1b97c5f3d715cd00cf3048bb06 100644 (file)
@@ -14,3 +14,6 @@
 [submodule "includes/zxcvbn"]
        path = src/static/js/zxcvbn
        url = https://github.com/dropbox/zxcvbn.git
+[submodule "src/flag-icons"]
+       path = src/flag-icons
+       url = https://github.com/lipis/flag-icon-css.git
index 1beefbcbe83ada87156c28306d18e47e01a1ec5f..96469d76198103f4f8e1be2546ecbea1165df022 100644 (file)
@@ -81,9 +81,9 @@ web_PYTHON = \
        src/web/download.py \
        src/web/handlers.py \
        src/web/handlers_fireinfo.py \
-       src/web/handlers_mirrors.py \
        src/web/iuse.py \
        src/web/location.py \
+       src/web/mirrors.py \
        src/web/newsletter.py \
        src/web/nopaste.py \
        src/web/people.py \
@@ -145,6 +145,12 @@ templates_location_DATA = \
 
 templates_locationdir = $(templatesdir)/location
 
+templates_mirrors_DATA = \
+       src/templates/mirrors/index.html \
+       src/templates/mirrors/mirror.html
+
+templates_mirrorsdir = $(templatesdir)/mirrors
+
 templates_modules_DATA = \
        src/templates/modules/map.html
 
@@ -252,6 +258,530 @@ static_css_DATA = \
 
 static_cssdir = $(staticdir)/css
 
+static_flagsdir = $(staticdir)/flags
+
+static_flags_1x1_DATA = \
+       src/flag-icons/flags/1x1/ad.svg \
+       src/flag-icons/flags/1x1/ae.svg \
+       src/flag-icons/flags/1x1/af.svg \
+       src/flag-icons/flags/1x1/ag.svg \
+       src/flag-icons/flags/1x1/ai.svg \
+       src/flag-icons/flags/1x1/al.svg \
+       src/flag-icons/flags/1x1/am.svg \
+       src/flag-icons/flags/1x1/ao.svg \
+       src/flag-icons/flags/1x1/aq.svg \
+       src/flag-icons/flags/1x1/ar.svg \
+       src/flag-icons/flags/1x1/as.svg \
+       src/flag-icons/flags/1x1/at.svg \
+       src/flag-icons/flags/1x1/au.svg \
+       src/flag-icons/flags/1x1/aw.svg \
+       src/flag-icons/flags/1x1/ax.svg \
+       src/flag-icons/flags/1x1/az.svg \
+       src/flag-icons/flags/1x1/ba.svg \
+       src/flag-icons/flags/1x1/bb.svg \
+       src/flag-icons/flags/1x1/bd.svg \
+       src/flag-icons/flags/1x1/be.svg \
+       src/flag-icons/flags/1x1/bf.svg \
+       src/flag-icons/flags/1x1/bg.svg \
+       src/flag-icons/flags/1x1/bh.svg \
+       src/flag-icons/flags/1x1/bi.svg \
+       src/flag-icons/flags/1x1/bj.svg \
+       src/flag-icons/flags/1x1/bl.svg \
+       src/flag-icons/flags/1x1/bm.svg \
+       src/flag-icons/flags/1x1/bn.svg \
+       src/flag-icons/flags/1x1/bo.svg \
+       src/flag-icons/flags/1x1/bq.svg \
+       src/flag-icons/flags/1x1/br.svg \
+       src/flag-icons/flags/1x1/bs.svg \
+       src/flag-icons/flags/1x1/bt.svg \
+       src/flag-icons/flags/1x1/bv.svg \
+       src/flag-icons/flags/1x1/bw.svg \
+       src/flag-icons/flags/1x1/by.svg \
+       src/flag-icons/flags/1x1/bz.svg \
+       src/flag-icons/flags/1x1/ca.svg \
+       src/flag-icons/flags/1x1/cc.svg \
+       src/flag-icons/flags/1x1/cd.svg \
+       src/flag-icons/flags/1x1/cf.svg \
+       src/flag-icons/flags/1x1/cg.svg \
+       src/flag-icons/flags/1x1/ch.svg \
+       src/flag-icons/flags/1x1/ci.svg \
+       src/flag-icons/flags/1x1/ck.svg \
+       src/flag-icons/flags/1x1/cl.svg \
+       src/flag-icons/flags/1x1/cm.svg \
+       src/flag-icons/flags/1x1/cn.svg \
+       src/flag-icons/flags/1x1/co.svg \
+       src/flag-icons/flags/1x1/cr.svg \
+       src/flag-icons/flags/1x1/cu.svg \
+       src/flag-icons/flags/1x1/cv.svg \
+       src/flag-icons/flags/1x1/cw.svg \
+       src/flag-icons/flags/1x1/cx.svg \
+       src/flag-icons/flags/1x1/cy.svg \
+       src/flag-icons/flags/1x1/cz.svg \
+       src/flag-icons/flags/1x1/de.svg \
+       src/flag-icons/flags/1x1/dj.svg \
+       src/flag-icons/flags/1x1/dk.svg \
+       src/flag-icons/flags/1x1/dm.svg \
+       src/flag-icons/flags/1x1/do.svg \
+       src/flag-icons/flags/1x1/dz.svg \
+       src/flag-icons/flags/1x1/ec.svg \
+       src/flag-icons/flags/1x1/ee.svg \
+       src/flag-icons/flags/1x1/eg.svg \
+       src/flag-icons/flags/1x1/eh.svg \
+       src/flag-icons/flags/1x1/er.svg \
+       src/flag-icons/flags/1x1/es-ct.svg \
+       src/flag-icons/flags/1x1/es.svg \
+       src/flag-icons/flags/1x1/et.svg \
+       src/flag-icons/flags/1x1/eu.svg \
+       src/flag-icons/flags/1x1/fi.svg \
+       src/flag-icons/flags/1x1/fj.svg \
+       src/flag-icons/flags/1x1/fk.svg \
+       src/flag-icons/flags/1x1/fm.svg \
+       src/flag-icons/flags/1x1/fo.svg \
+       src/flag-icons/flags/1x1/fr.svg \
+       src/flag-icons/flags/1x1/ga.svg \
+       src/flag-icons/flags/1x1/gb-eng.svg \
+       src/flag-icons/flags/1x1/gb-nir.svg \
+       src/flag-icons/flags/1x1/gb-sct.svg \
+       src/flag-icons/flags/1x1/gb.svg \
+       src/flag-icons/flags/1x1/gb-wls.svg \
+       src/flag-icons/flags/1x1/gd.svg \
+       src/flag-icons/flags/1x1/ge.svg \
+       src/flag-icons/flags/1x1/gf.svg \
+       src/flag-icons/flags/1x1/gg.svg \
+       src/flag-icons/flags/1x1/gh.svg \
+       src/flag-icons/flags/1x1/gi.svg \
+       src/flag-icons/flags/1x1/gl.svg \
+       src/flag-icons/flags/1x1/gm.svg \
+       src/flag-icons/flags/1x1/gn.svg \
+       src/flag-icons/flags/1x1/gp.svg \
+       src/flag-icons/flags/1x1/gq.svg \
+       src/flag-icons/flags/1x1/gr.svg \
+       src/flag-icons/flags/1x1/gs.svg \
+       src/flag-icons/flags/1x1/gt.svg \
+       src/flag-icons/flags/1x1/gu.svg \
+       src/flag-icons/flags/1x1/gw.svg \
+       src/flag-icons/flags/1x1/gy.svg \
+       src/flag-icons/flags/1x1/hk.svg \
+       src/flag-icons/flags/1x1/hm.svg \
+       src/flag-icons/flags/1x1/hn.svg \
+       src/flag-icons/flags/1x1/hr.svg \
+       src/flag-icons/flags/1x1/ht.svg \
+       src/flag-icons/flags/1x1/hu.svg \
+       src/flag-icons/flags/1x1/id.svg \
+       src/flag-icons/flags/1x1/ie.svg \
+       src/flag-icons/flags/1x1/il.svg \
+       src/flag-icons/flags/1x1/im.svg \
+       src/flag-icons/flags/1x1/in.svg \
+       src/flag-icons/flags/1x1/io.svg \
+       src/flag-icons/flags/1x1/iq.svg \
+       src/flag-icons/flags/1x1/ir.svg \
+       src/flag-icons/flags/1x1/is.svg \
+       src/flag-icons/flags/1x1/it.svg \
+       src/flag-icons/flags/1x1/je.svg \
+       src/flag-icons/flags/1x1/jm.svg \
+       src/flag-icons/flags/1x1/jo.svg \
+       src/flag-icons/flags/1x1/jp.svg \
+       src/flag-icons/flags/1x1/ke.svg \
+       src/flag-icons/flags/1x1/kg.svg \
+       src/flag-icons/flags/1x1/kh.svg \
+       src/flag-icons/flags/1x1/ki.svg \
+       src/flag-icons/flags/1x1/km.svg \
+       src/flag-icons/flags/1x1/kn.svg \
+       src/flag-icons/flags/1x1/kp.svg \
+       src/flag-icons/flags/1x1/kr.svg \
+       src/flag-icons/flags/1x1/kw.svg \
+       src/flag-icons/flags/1x1/ky.svg \
+       src/flag-icons/flags/1x1/kz.svg \
+       src/flag-icons/flags/1x1/la.svg \
+       src/flag-icons/flags/1x1/lb.svg \
+       src/flag-icons/flags/1x1/lc.svg \
+       src/flag-icons/flags/1x1/li.svg \
+       src/flag-icons/flags/1x1/lk.svg \
+       src/flag-icons/flags/1x1/lr.svg \
+       src/flag-icons/flags/1x1/ls.svg \
+       src/flag-icons/flags/1x1/lt.svg \
+       src/flag-icons/flags/1x1/lu.svg \
+       src/flag-icons/flags/1x1/lv.svg \
+       src/flag-icons/flags/1x1/ly.svg \
+       src/flag-icons/flags/1x1/ma.svg \
+       src/flag-icons/flags/1x1/mc.svg \
+       src/flag-icons/flags/1x1/md.svg \
+       src/flag-icons/flags/1x1/me.svg \
+       src/flag-icons/flags/1x1/mf.svg \
+       src/flag-icons/flags/1x1/mg.svg \
+       src/flag-icons/flags/1x1/mh.svg \
+       src/flag-icons/flags/1x1/mk.svg \
+       src/flag-icons/flags/1x1/ml.svg \
+       src/flag-icons/flags/1x1/mm.svg \
+       src/flag-icons/flags/1x1/mn.svg \
+       src/flag-icons/flags/1x1/mo.svg \
+       src/flag-icons/flags/1x1/mp.svg \
+       src/flag-icons/flags/1x1/mq.svg \
+       src/flag-icons/flags/1x1/mr.svg \
+       src/flag-icons/flags/1x1/ms.svg \
+       src/flag-icons/flags/1x1/mt.svg \
+       src/flag-icons/flags/1x1/mu.svg \
+       src/flag-icons/flags/1x1/mv.svg \
+       src/flag-icons/flags/1x1/mw.svg \
+       src/flag-icons/flags/1x1/mx.svg \
+       src/flag-icons/flags/1x1/my.svg \
+       src/flag-icons/flags/1x1/mz.svg \
+       src/flag-icons/flags/1x1/na.svg \
+       src/flag-icons/flags/1x1/nc.svg \
+       src/flag-icons/flags/1x1/ne.svg \
+       src/flag-icons/flags/1x1/nf.svg \
+       src/flag-icons/flags/1x1/ng.svg \
+       src/flag-icons/flags/1x1/ni.svg \
+       src/flag-icons/flags/1x1/nl.svg \
+       src/flag-icons/flags/1x1/no.svg \
+       src/flag-icons/flags/1x1/np.svg \
+       src/flag-icons/flags/1x1/nr.svg \
+       src/flag-icons/flags/1x1/nu.svg \
+       src/flag-icons/flags/1x1/nz.svg \
+       src/flag-icons/flags/1x1/om.svg \
+       src/flag-icons/flags/1x1/pa.svg \
+       src/flag-icons/flags/1x1/pe.svg \
+       src/flag-icons/flags/1x1/pf.svg \
+       src/flag-icons/flags/1x1/pg.svg \
+       src/flag-icons/flags/1x1/ph.svg \
+       src/flag-icons/flags/1x1/pk.svg \
+       src/flag-icons/flags/1x1/pl.svg \
+       src/flag-icons/flags/1x1/pm.svg \
+       src/flag-icons/flags/1x1/pn.svg \
+       src/flag-icons/flags/1x1/pr.svg \
+       src/flag-icons/flags/1x1/ps.svg \
+       src/flag-icons/flags/1x1/pt.svg \
+       src/flag-icons/flags/1x1/pw.svg \
+       src/flag-icons/flags/1x1/py.svg \
+       src/flag-icons/flags/1x1/qa.svg \
+       src/flag-icons/flags/1x1/re.svg \
+       src/flag-icons/flags/1x1/ro.svg \
+       src/flag-icons/flags/1x1/rs.svg \
+       src/flag-icons/flags/1x1/ru.svg \
+       src/flag-icons/flags/1x1/rw.svg \
+       src/flag-icons/flags/1x1/sa.svg \
+       src/flag-icons/flags/1x1/sb.svg \
+       src/flag-icons/flags/1x1/sc.svg \
+       src/flag-icons/flags/1x1/sd.svg \
+       src/flag-icons/flags/1x1/se.svg \
+       src/flag-icons/flags/1x1/sg.svg \
+       src/flag-icons/flags/1x1/sh.svg \
+       src/flag-icons/flags/1x1/si.svg \
+       src/flag-icons/flags/1x1/sj.svg \
+       src/flag-icons/flags/1x1/sk.svg \
+       src/flag-icons/flags/1x1/sl.svg \
+       src/flag-icons/flags/1x1/sm.svg \
+       src/flag-icons/flags/1x1/sn.svg \
+       src/flag-icons/flags/1x1/so.svg \
+       src/flag-icons/flags/1x1/sr.svg \
+       src/flag-icons/flags/1x1/ss.svg \
+       src/flag-icons/flags/1x1/st.svg \
+       src/flag-icons/flags/1x1/sv.svg \
+       src/flag-icons/flags/1x1/sx.svg \
+       src/flag-icons/flags/1x1/sy.svg \
+       src/flag-icons/flags/1x1/sz.svg \
+       src/flag-icons/flags/1x1/tc.svg \
+       src/flag-icons/flags/1x1/td.svg \
+       src/flag-icons/flags/1x1/tf.svg \
+       src/flag-icons/flags/1x1/tg.svg \
+       src/flag-icons/flags/1x1/th.svg \
+       src/flag-icons/flags/1x1/tj.svg \
+       src/flag-icons/flags/1x1/tk.svg \
+       src/flag-icons/flags/1x1/tl.svg \
+       src/flag-icons/flags/1x1/tm.svg \
+       src/flag-icons/flags/1x1/tn.svg \
+       src/flag-icons/flags/1x1/to.svg \
+       src/flag-icons/flags/1x1/tr.svg \
+       src/flag-icons/flags/1x1/tt.svg \
+       src/flag-icons/flags/1x1/tv.svg \
+       src/flag-icons/flags/1x1/tw.svg \
+       src/flag-icons/flags/1x1/tz.svg \
+       src/flag-icons/flags/1x1/ua.svg \
+       src/flag-icons/flags/1x1/ug.svg \
+       src/flag-icons/flags/1x1/um.svg \
+       src/flag-icons/flags/1x1/un.svg \
+       src/flag-icons/flags/1x1/us.svg \
+       src/flag-icons/flags/1x1/uy.svg \
+       src/flag-icons/flags/1x1/uz.svg \
+       src/flag-icons/flags/1x1/va.svg \
+       src/flag-icons/flags/1x1/vc.svg \
+       src/flag-icons/flags/1x1/ve.svg \
+       src/flag-icons/flags/1x1/vg.svg \
+       src/flag-icons/flags/1x1/vi.svg \
+       src/flag-icons/flags/1x1/vn.svg \
+       src/flag-icons/flags/1x1/vu.svg \
+       src/flag-icons/flags/1x1/wf.svg \
+       src/flag-icons/flags/1x1/ws.svg \
+       src/flag-icons/flags/1x1/xk.svg \
+       src/flag-icons/flags/1x1/ye.svg \
+       src/flag-icons/flags/1x1/yt.svg \
+       src/flag-icons/flags/1x1/za.svg \
+       src/flag-icons/flags/1x1/zm.svg \
+       src/flag-icons/flags/1x1/zw.svg
+
+static_flags_1x1dir = $(static_flagsdir)/1x1
+
+static_flags_4x3_DATA = \
+       src/flag-icons/flags/4x3/ad.svg \
+       src/flag-icons/flags/4x3/ae.svg \
+       src/flag-icons/flags/4x3/af.svg \
+       src/flag-icons/flags/4x3/ag.svg \
+       src/flag-icons/flags/4x3/ai.svg \
+       src/flag-icons/flags/4x3/al.svg \
+       src/flag-icons/flags/4x3/am.svg \
+       src/flag-icons/flags/4x3/ao.svg \
+       src/flag-icons/flags/4x3/aq.svg \
+       src/flag-icons/flags/4x3/ar.svg \
+       src/flag-icons/flags/4x3/as.svg \
+       src/flag-icons/flags/4x3/at.svg \
+       src/flag-icons/flags/4x3/au.svg \
+       src/flag-icons/flags/4x3/aw.svg \
+       src/flag-icons/flags/4x3/ax.svg \
+       src/flag-icons/flags/4x3/az.svg \
+       src/flag-icons/flags/4x3/ba.svg \
+       src/flag-icons/flags/4x3/bb.svg \
+       src/flag-icons/flags/4x3/bd.svg \
+       src/flag-icons/flags/4x3/be.svg \
+       src/flag-icons/flags/4x3/bf.svg \
+       src/flag-icons/flags/4x3/bg.svg \
+       src/flag-icons/flags/4x3/bh.svg \
+       src/flag-icons/flags/4x3/bi.svg \
+       src/flag-icons/flags/4x3/bj.svg \
+       src/flag-icons/flags/4x3/bl.svg \
+       src/flag-icons/flags/4x3/bm.svg \
+       src/flag-icons/flags/4x3/bn.svg \
+       src/flag-icons/flags/4x3/bo.svg \
+       src/flag-icons/flags/4x3/bq.svg \
+       src/flag-icons/flags/4x3/br.svg \
+       src/flag-icons/flags/4x3/bs.svg \
+       src/flag-icons/flags/4x3/bt.svg \
+       src/flag-icons/flags/4x3/bv.svg \
+       src/flag-icons/flags/4x3/bw.svg \
+       src/flag-icons/flags/4x3/by.svg \
+       src/flag-icons/flags/4x3/bz.svg \
+       src/flag-icons/flags/4x3/ca.svg \
+       src/flag-icons/flags/4x3/cc.svg \
+       src/flag-icons/flags/4x3/cd.svg \
+       src/flag-icons/flags/4x3/cf.svg \
+       src/flag-icons/flags/4x3/cg.svg \
+       src/flag-icons/flags/4x3/ch.svg \
+       src/flag-icons/flags/4x3/ci.svg \
+       src/flag-icons/flags/4x3/ck.svg \
+       src/flag-icons/flags/4x3/cl.svg \
+       src/flag-icons/flags/4x3/cm.svg \
+       src/flag-icons/flags/4x3/cn.svg \
+       src/flag-icons/flags/4x3/co.svg \
+       src/flag-icons/flags/4x3/cr.svg \
+       src/flag-icons/flags/4x3/cu.svg \
+       src/flag-icons/flags/4x3/cv.svg \
+       src/flag-icons/flags/4x3/cw.svg \
+       src/flag-icons/flags/4x3/cx.svg \
+       src/flag-icons/flags/4x3/cy.svg \
+       src/flag-icons/flags/4x3/cz.svg \
+       src/flag-icons/flags/4x3/de.svg \
+       src/flag-icons/flags/4x3/dj.svg \
+       src/flag-icons/flags/4x3/dk.svg \
+       src/flag-icons/flags/4x3/dm.svg \
+       src/flag-icons/flags/4x3/do.svg \
+       src/flag-icons/flags/4x3/dz.svg \
+       src/flag-icons/flags/4x3/ec.svg \
+       src/flag-icons/flags/4x3/ee.svg \
+       src/flag-icons/flags/4x3/eg.svg \
+       src/flag-icons/flags/4x3/eh.svg \
+       src/flag-icons/flags/4x3/er.svg \
+       src/flag-icons/flags/4x3/es-ct.svg \
+       src/flag-icons/flags/4x3/es.svg \
+       src/flag-icons/flags/4x3/et.svg \
+       src/flag-icons/flags/4x3/eu.svg \
+       src/flag-icons/flags/4x3/fi.svg \
+       src/flag-icons/flags/4x3/fj.svg \
+       src/flag-icons/flags/4x3/fk.svg \
+       src/flag-icons/flags/4x3/fm.svg \
+       src/flag-icons/flags/4x3/fo.svg \
+       src/flag-icons/flags/4x3/fr.svg \
+       src/flag-icons/flags/4x3/ga.svg \
+       src/flag-icons/flags/4x3/gb-eng.svg \
+       src/flag-icons/flags/4x3/gb-nir.svg \
+       src/flag-icons/flags/4x3/gb-sct.svg \
+       src/flag-icons/flags/4x3/gb.svg \
+       src/flag-icons/flags/4x3/gb-wls.svg \
+       src/flag-icons/flags/4x3/gd.svg \
+       src/flag-icons/flags/4x3/ge.svg \
+       src/flag-icons/flags/4x3/gf.svg \
+       src/flag-icons/flags/4x3/gg.svg \
+       src/flag-icons/flags/4x3/gh.svg \
+       src/flag-icons/flags/4x3/gi.svg \
+       src/flag-icons/flags/4x3/gl.svg \
+       src/flag-icons/flags/4x3/gm.svg \
+       src/flag-icons/flags/4x3/gn.svg \
+       src/flag-icons/flags/4x3/gp.svg \
+       src/flag-icons/flags/4x3/gq.svg \
+       src/flag-icons/flags/4x3/gr.svg \
+       src/flag-icons/flags/4x3/gs.svg \
+       src/flag-icons/flags/4x3/gt.svg \
+       src/flag-icons/flags/4x3/gu.svg \
+       src/flag-icons/flags/4x3/gw.svg \
+       src/flag-icons/flags/4x3/gy.svg \
+       src/flag-icons/flags/4x3/hk.svg \
+       src/flag-icons/flags/4x3/hm.svg \
+       src/flag-icons/flags/4x3/hn.svg \
+       src/flag-icons/flags/4x3/hr.svg \
+       src/flag-icons/flags/4x3/ht.svg \
+       src/flag-icons/flags/4x3/hu.svg \
+       src/flag-icons/flags/4x3/id.svg \
+       src/flag-icons/flags/4x3/ie.svg \
+       src/flag-icons/flags/4x3/il.svg \
+       src/flag-icons/flags/4x3/im.svg \
+       src/flag-icons/flags/4x3/in.svg \
+       src/flag-icons/flags/4x3/io.svg \
+       src/flag-icons/flags/4x3/iq.svg \
+       src/flag-icons/flags/4x3/ir.svg \
+       src/flag-icons/flags/4x3/is.svg \
+       src/flag-icons/flags/4x3/it.svg \
+       src/flag-icons/flags/4x3/je.svg \
+       src/flag-icons/flags/4x3/jm.svg \
+       src/flag-icons/flags/4x3/jo.svg \
+       src/flag-icons/flags/4x3/jp.svg \
+       src/flag-icons/flags/4x3/ke.svg \
+       src/flag-icons/flags/4x3/kg.svg \
+       src/flag-icons/flags/4x3/kh.svg \
+       src/flag-icons/flags/4x3/ki.svg \
+       src/flag-icons/flags/4x3/km.svg \
+       src/flag-icons/flags/4x3/kn.svg \
+       src/flag-icons/flags/4x3/kp.svg \
+       src/flag-icons/flags/4x3/kr.svg \
+       src/flag-icons/flags/4x3/kw.svg \
+       src/flag-icons/flags/4x3/ky.svg \
+       src/flag-icons/flags/4x3/kz.svg \
+       src/flag-icons/flags/4x3/la.svg \
+       src/flag-icons/flags/4x3/lb.svg \
+       src/flag-icons/flags/4x3/lc.svg \
+       src/flag-icons/flags/4x3/li.svg \
+       src/flag-icons/flags/4x3/lk.svg \
+       src/flag-icons/flags/4x3/lr.svg \
+       src/flag-icons/flags/4x3/ls.svg \
+       src/flag-icons/flags/4x3/lt.svg \
+       src/flag-icons/flags/4x3/lu.svg \
+       src/flag-icons/flags/4x3/lv.svg \
+       src/flag-icons/flags/4x3/ly.svg \
+       src/flag-icons/flags/4x3/ma.svg \
+       src/flag-icons/flags/4x3/mc.svg \
+       src/flag-icons/flags/4x3/md.svg \
+       src/flag-icons/flags/4x3/me.svg \
+       src/flag-icons/flags/4x3/mf.svg \
+       src/flag-icons/flags/4x3/mg.svg \
+       src/flag-icons/flags/4x3/mh.svg \
+       src/flag-icons/flags/4x3/mk.svg \
+       src/flag-icons/flags/4x3/ml.svg \
+       src/flag-icons/flags/4x3/mm.svg \
+       src/flag-icons/flags/4x3/mn.svg \
+       src/flag-icons/flags/4x3/mo.svg \
+       src/flag-icons/flags/4x3/mp.svg \
+       src/flag-icons/flags/4x3/mq.svg \
+       src/flag-icons/flags/4x3/mr.svg \
+       src/flag-icons/flags/4x3/ms.svg \
+       src/flag-icons/flags/4x3/mt.svg \
+       src/flag-icons/flags/4x3/mu.svg \
+       src/flag-icons/flags/4x3/mv.svg \
+       src/flag-icons/flags/4x3/mw.svg \
+       src/flag-icons/flags/4x3/mx.svg \
+       src/flag-icons/flags/4x3/my.svg \
+       src/flag-icons/flags/4x3/mz.svg \
+       src/flag-icons/flags/4x3/na.svg \
+       src/flag-icons/flags/4x3/nc.svg \
+       src/flag-icons/flags/4x3/ne.svg \
+       src/flag-icons/flags/4x3/nf.svg \
+       src/flag-icons/flags/4x3/ng.svg \
+       src/flag-icons/flags/4x3/ni.svg \
+       src/flag-icons/flags/4x3/nl.svg \
+       src/flag-icons/flags/4x3/no.svg \
+       src/flag-icons/flags/4x3/np.svg \
+       src/flag-icons/flags/4x3/nr.svg \
+       src/flag-icons/flags/4x3/nu.svg \
+       src/flag-icons/flags/4x3/nz.svg \
+       src/flag-icons/flags/4x3/om.svg \
+       src/flag-icons/flags/4x3/pa.svg \
+       src/flag-icons/flags/4x3/pe.svg \
+       src/flag-icons/flags/4x3/pf.svg \
+       src/flag-icons/flags/4x3/pg.svg \
+       src/flag-icons/flags/4x3/ph.svg \
+       src/flag-icons/flags/4x3/pk.svg \
+       src/flag-icons/flags/4x3/pl.svg \
+       src/flag-icons/flags/4x3/pm.svg \
+       src/flag-icons/flags/4x3/pn.svg \
+       src/flag-icons/flags/4x3/pr.svg \
+       src/flag-icons/flags/4x3/ps.svg \
+       src/flag-icons/flags/4x3/pt.svg \
+       src/flag-icons/flags/4x3/pw.svg \
+       src/flag-icons/flags/4x3/py.svg \
+       src/flag-icons/flags/4x3/qa.svg \
+       src/flag-icons/flags/4x3/re.svg \
+       src/flag-icons/flags/4x3/ro.svg \
+       src/flag-icons/flags/4x3/rs.svg \
+       src/flag-icons/flags/4x3/ru.svg \
+       src/flag-icons/flags/4x3/rw.svg \
+       src/flag-icons/flags/4x3/sa.svg \
+       src/flag-icons/flags/4x3/sb.svg \
+       src/flag-icons/flags/4x3/sc.svg \
+       src/flag-icons/flags/4x3/sd.svg \
+       src/flag-icons/flags/4x3/se.svg \
+       src/flag-icons/flags/4x3/sg.svg \
+       src/flag-icons/flags/4x3/sh.svg \
+       src/flag-icons/flags/4x3/si.svg \
+       src/flag-icons/flags/4x3/sj.svg \
+       src/flag-icons/flags/4x3/sk.svg \
+       src/flag-icons/flags/4x3/sl.svg \
+       src/flag-icons/flags/4x3/sm.svg \
+       src/flag-icons/flags/4x3/sn.svg \
+       src/flag-icons/flags/4x3/so.svg \
+       src/flag-icons/flags/4x3/sr.svg \
+       src/flag-icons/flags/4x3/ss.svg \
+       src/flag-icons/flags/4x3/st.svg \
+       src/flag-icons/flags/4x3/sv.svg \
+       src/flag-icons/flags/4x3/sx.svg \
+       src/flag-icons/flags/4x3/sy.svg \
+       src/flag-icons/flags/4x3/sz.svg \
+       src/flag-icons/flags/4x3/tc.svg \
+       src/flag-icons/flags/4x3/td.svg \
+       src/flag-icons/flags/4x3/tf.svg \
+       src/flag-icons/flags/4x3/tg.svg \
+       src/flag-icons/flags/4x3/th.svg \
+       src/flag-icons/flags/4x3/tj.svg \
+       src/flag-icons/flags/4x3/tk.svg \
+       src/flag-icons/flags/4x3/tl.svg \
+       src/flag-icons/flags/4x3/tm.svg \
+       src/flag-icons/flags/4x3/tn.svg \
+       src/flag-icons/flags/4x3/to.svg \
+       src/flag-icons/flags/4x3/tr.svg \
+       src/flag-icons/flags/4x3/tt.svg \
+       src/flag-icons/flags/4x3/tv.svg \
+       src/flag-icons/flags/4x3/tw.svg \
+       src/flag-icons/flags/4x3/tz.svg \
+       src/flag-icons/flags/4x3/ua.svg \
+       src/flag-icons/flags/4x3/ug.svg \
+       src/flag-icons/flags/4x3/um.svg \
+       src/flag-icons/flags/4x3/un.svg \
+       src/flag-icons/flags/4x3/us.svg \
+       src/flag-icons/flags/4x3/uy.svg \
+       src/flag-icons/flags/4x3/uz.svg \
+       src/flag-icons/flags/4x3/va.svg \
+       src/flag-icons/flags/4x3/vc.svg \
+       src/flag-icons/flags/4x3/ve.svg \
+       src/flag-icons/flags/4x3/vg.svg \
+       src/flag-icons/flags/4x3/vi.svg \
+       src/flag-icons/flags/4x3/vn.svg \
+       src/flag-icons/flags/4x3/vu.svg \
+       src/flag-icons/flags/4x3/wf.svg \
+       src/flag-icons/flags/4x3/ws.svg \
+       src/flag-icons/flags/4x3/xk.svg \
+       src/flag-icons/flags/4x3/ye.svg \
+       src/flag-icons/flags/4x3/yt.svg \
+       src/flag-icons/flags/4x3/za.svg \
+       src/flag-icons/flags/4x3/zm.svg \
+       src/flag-icons/flags/4x3/zw.svg
+
+static_flags_4x3dir = $(static_flagsdir)/4x3
+
 static_fonts_DATA = \
        src/fonts/ofl/mukta/Mukta-Bold.ttf \
        src/fonts/ofl/mukta/Mukta-ExtraBold.ttf \
index 0b743a79fc5d1efe93a0974f53a54aac3a3faef1..97526943f7475bff90d33af4648305e80f6d989f 100644 (file)
@@ -12,6 +12,7 @@ import tornado.netutil
 import urllib.parse
 
 from .misc import Object
+from .decorators import *
 
 class Downloads(Object):
        @property
@@ -80,23 +81,25 @@ class Downloads(Object):
 
 
 class Mirrors(Object):
+       def _get_mirrors(self, query, *args):
+               res = self.db.query(query, *args)
+
+               for row in res:
+                       yield Mirror(self.backend, row.id, data=row)
+
+       def __iter__(self):
+               mirrors = self._get_mirrors("SELECT * FROM mirrors \
+                       WHERE enabled IS TRUE ORDER BY hostname")
+
+               return iter(mirrors)
+
        def check_all(self):
-               for mirror in self.get_all():
+               for mirror in self:
                        mirror.check()
 
        def get(self, id):
                return Mirror(self.backend, id)
 
-       def get_all(self):
-               res = self.db.query("SELECT * FROM mirrors WHERE enabled = %s", True)
-
-               mirrors = []
-               for row in res:
-                       mirror = Mirror(self.backend, row.id, row)
-                       mirrors.append(mirror)
-
-               return MirrorSet(self.backend, sorted(mirrors))
-
        def get_by_hostname(self, hostname):
                ret = self.db.get("SELECT * FROM mirrors WHERE hostname = %s", hostname)
 
@@ -156,7 +159,7 @@ class Mirrors(Object):
        def get_all_files(self):
                files = []
 
-               for mirror in self.get_all():
+               for mirror in self:
                        if not mirror.state == "UP":
                                continue
 
@@ -273,51 +276,49 @@ class MirrorSet(Object):
 
 
 class Mirror(Object):
-       def __init__(self, backend, id, data=None):
-               Object.__init__(self, backend)
-
-               self.id = id
-
-               if data:
-                       self._info = data
-               else:
-                       self._info = self.db.get("SELECT * FROM mirrors WHERE id = %s", self.id)
-               self._info["url"] = self.generate_url()
+       def init(self, id, data=None):
+               self.id   = id
+               self.data = data
 
-               self.__location = None
-               self.__country_name = None
+       def __str__(self):
+               return self.hostname
 
        def __repr__(self):
                return "<%s %s>" % (self.__class__.__name__, self.url)
 
-       def __cmp__(self, other):
-               ret = cmp(self.country_code, other.country_code)
-
-               if not ret:
-                       ret = cmp(self.hostname, other.hostname)
+       def __eq__(self, other):
+               if isinstance(other, self.__class__):
+                       return self.id == other.id
 
-               return ret
+       def __lt__(self, other):
+               if isinstance(other, self.__class__):
+                       return self.hostname < other.hostname
 
-       def generate_url(self):
+       @lazy_property
+       def url(self):
                url = "%s://%s" % ("https" if self.supports_https else "http", self.hostname)
+
                if not self.path.startswith("/"):
                        url += "/"
+
                url += "%s" % self.path
+
                if not self.path.endswith("/"):
                        url += "/"
+
                return url
 
        @property
        def hostname(self):
-               return self._info.hostname
+               return self.data.hostname
 
        @property
        def path(self):
-               return self._info.path
+               return self.data.path
 
        @property
        def supports_https(self):
-               return self._info.supports_https
+               return self.data.supports_https
 
        @property
        def address(self):
@@ -329,14 +330,11 @@ class Mirror(Object):
 
        @property
        def owner(self):
-               return self._info.owner
+               return self.data.owner
 
-       @property
+       @lazy_property
        def location(self):
-               if self.__location is None:
-                       self.__location = self.geoip.get_location(self.address)
-
-               return self.__location
+               return self.geoip.get_location(self.address)
 
        @property
        def latitude(self):
@@ -348,19 +346,6 @@ class Mirror(Object):
                if self.location:
                        return self.location.longitude
 
-       @property
-       def coordinates(self):
-               return (self.latitude, self.longitude)
-
-       @property
-       def coordiante_str(self):
-               coordinates = []
-
-               for i in self.coordinates:
-                       coordinates.append("%s" % i)
-
-               return ",".join(coordinates)
-
        @property
        def country_code(self):
                if self.location:
@@ -368,30 +353,11 @@ class Mirror(Object):
 
        @property
        def country_name(self):
-               if self.__country_name is None:
-                       self.__country_name = self.geoip.get_country_name(self.country_code)
-
-               return self.__country_name
-
-       @property
-       def location_str(self):
-               location = []
-
-               if self._info.location:
-                       location.append(self._info.location)
+               return self.geoip.get_country_name(self.country_code)
 
-               elif self.location:
-                       location.append(self.location.city)
-                       location.append(self.country_name)
-
-               return ", ".join([s for s in location if s])
-
-       @property
+       @lazy_property
        def asn(self):
-               if not hasattr(self, "__asn"):
-                       self.__asn = self.geoip.get_asn(self.address)
-
-               return self.__asn
+               return self.geoip.get_asn(self.address)
 
        @property
        def filelist(self):
@@ -402,20 +368,16 @@ class Mirror(Object):
        def prefix(self):
                return ""
 
-       @property
-       def url(self):
-               return self._info.url
-
        def build_url(self, filename):
                return urllib.parse.urljoin(self.url, filename)
 
        @property
        def last_update(self):
-               return self._info.last_update
+               return self.data.last_update
 
        @property
        def state(self):
-               return self._info.state
+               return self.data.state
 
        def set_state(self, state):
                logging.info("Setting state of %s to %s" % (self.hostname, state))
@@ -426,12 +388,11 @@ class Mirror(Object):
                self.db.execute("UPDATE mirrors SET state = %s WHERE id = %s", state, self.id)
 
                # Reload changed settings
-               if hasattr(self, "_info"):
-                       self._info["state"] = state
+               self.data["state"] = state
 
        @property
        def enabled(self):
-               return self._info.enabled
+               return self.data.enabled
 
        @property
        def disabled(self):
@@ -494,8 +455,7 @@ class Mirror(Object):
                        timestamp, self.id)
 
                # Reload changed settings
-               if hasattr(self, "_info"):
-                       self._info["timestamp"] = timestamp
+               self.data["timestamp"] = timestamp
 
                self.check_state()
 
@@ -537,7 +497,7 @@ class Mirror(Object):
 
        @property
        def prefer_for_countries(self):
-               countries = self._info.get("prefer_for_countries", "")
+               countries = self.data.get("prefer_for_countries", "")
                if countries:
                        return sorted(countries.split(", "))
 
@@ -585,34 +545,17 @@ class Mirror(Object):
 
                return c * earth
 
-       def traffic(self, since):
-               # XXX needs to be done better
-
-               files = {}
-               for entry in self.db.query("SELECT filename, filesize FROM files"):
-                       files[entry.filename] = entry.filesize
-
-               query = "SELECT COUNT(filename) as count, filename FROM log_download WHERE mirror = %s"
-               query += " AND date >= %s GROUP BY filename"
-
-               traffic = 0
-               for entry in self.db.query(query, self.id, since):
-                       if entry.filename in files:
-                               traffic += entry.count * files[entry.filename]
-
-               return traffic
-
        @property
        def priority(self):
-               return self._info.get("priority", 10)
+               return self.data.get("priority", 10)
 
        @property
        def development(self):
-               return self._info.get("mirrorlist_devel", False)
+               return self.data.get("mirrorlist_devel", False)
 
        @property
        def mirrorlist(self):
-               return self._info.get("mirrorlist", False)
+               return self.data.get("mirrorlist", False)
 
        @property
        def addresses(self):
diff --git a/src/flag-icons b/src/flag-icons
new file mode 160000 (submodule)
index 0000000..45f302d
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 45f302d50b931a08aed5246b7992b4a41ee8b592
index 940e16e97297cbce5468329de2a596ccae41d427..eee205951fcc06b9ddc8be3b997228ebb11cc323 100644 (file)
@@ -15,3 +15,9 @@ $pf-font-path:              "fonts";
 $pf-font-size-base:         $font-size-base;
 
 @import "../payment-font/sass/paymentfont";
+
+// Flags
+
+$flag-icon-css-path:        "flags";
+
+@import "../flag-icons/sass/flag-icon";
index 3ceb196072a1c5b7d12b3244d0cc7ba0387adf70..3e7946d4a0e1d6a1bcc622984b436bbaa476d619 100644 (file)
@@ -36,7 +36,7 @@
 @import "fonts";
 
 // Custom stuff
-@import '_icons';
+@import "icons";
 
 // Makes everything white with dark text on it
 .inverse {
diff --git a/src/templates/mirrors-item.html b/src/templates/mirrors-item.html
deleted file mode 100644 (file)
index 6a477ae..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}{{ _("Mirror %s") % item.hostname }}{% end block %}
-
-{% block body %}
-       <div class="page-header">
-               {% if item.state == "UP" %}
-                       <span class="label label-success pull-right">{{ _("Up") }}</span>
-               {% elif item.state == "DOWN" %}
-                       <span class="label label-failure pull-right">{{ _("Down") }}</span>
-               {% elif item.state == "OUTOFSYNC" %}
-                       <span class="label label-warning pull-right">{{ _("Out of sync") }}</span>
-               {% else %}
-                       <span class="label label-info pull-right">{{ _("Unknown") }}</span>
-               {% end %}
-
-               <h1>{{ item.hostname }}</h1>
-       </div>
-
-       <div class="row">
-               <div class="col-lg-4 col-md-4">
-                       {% if item.owner %}
-                               <dt>{{ _("Owner") }}</dt>
-                               <dd>{{ item.owner }}</dd>
-                       {% end %}
-
-                       {% if item.location_str %}
-                               <hr>
-
-                               <dt>{{ _("Location") }}</dt>
-                               <dd>{{ item.location_str }}</dd>
-                       {% elif item.location %}
-                               <hr>
-
-                               {% if item.country_name %}
-                                       <dt>{{ _("Country") }}</dt>
-                                       <dd>{{ item.country_name }}</dd>
-                               {% end %}
-
-                               {% if item.location.city %}
-                                       <dt>{{ _("City") }}</dt>
-                                       <dd>{{ item.location.city }}</dd>
-                               {% end %}
-                       {% end %}
-
-                       {% if item.prefer_for_countries %}
-                               <dt>{{ _("Preferred for") }}</dt>
-                               <dd>
-                                       {{ locale.list(item.prefer_for_countries_names) }}
-                               </dd>
-                       {% end %}
-
-                       {% if client_distance %}
-                               <dt>{{ _("Estimated distance to you") }}</dt>
-                               <dd>{{ "%.0fkm" % client_distance }}</dd>
-                       {% end %}
-
-                       <hr>
-
-                       {% if item.asn %}
-                               <dt>{{ _("Autonomous System") }}</dt>
-                               <dd>{{ item.asn }}</dd>
-                       {% end %}
-
-                       <dt>{{ _("IP Addresses") }}</dt>
-                       <dd>
-                               {% for addr in item.addresses6 + item.addresses4 %}
-                                       {{ addr }}<br>
-                               {% end %}
-                       </dd>
-
-                       {% if item.enabled %}
-                               <hr>
-
-                               <dt>{{ _("Last updated") }}</dt>
-                               <dd>
-                                       <abbr title="{{ locale.format_date(item.last_update, full_format=True) }} UTC">
-                                               {{ locale.format_date(item.last_update, relative=True) }}
-                                       </abbr>
-                               </dd>
-                       {% end %}
-
-                       <hr>
-
-                       <p class="ac">
-                               <a class="btn btn-default" href="{{ item.url }}">{{ _("Go to mirror") }}</a>
-                       </p>
-               </div>
-
-               <div class="col-lg-8 col-md-8">
-                       {% if item.location %}
-                               {% module Map(item.latitude, item.longitude) %}
-                               <p class="text-muted ac">
-                                       {{ _("The location of the mirror server is estimated by the IP address.") }}
-                               </p>
-                       {% else %}
-                               <p class="ac text-muted">
-                                       {{ _("The location of this mirror server could not be estimated.") }}
-                               </p>
-                       {% end %}
-               </div>
-       </div>
-{% end block %}
diff --git a/src/templates/mirrors.html b/src/templates/mirrors.html
deleted file mode 100644 (file)
index cd45596..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Mirrors{% end block %}
-
-{% block body %}
-<div class="container">
-       <section class="features-content col-12">
-               <h2 class="display-2 text-center mb-0">mirrors.ipfire.org</h2>
-
-               <p class="lead">
-                       The IPFire project is hosted on several servers to provide a high
-                       availability of service and download speed from any place
-                       on the world.
-               </p>
-
-               {% module MirrorsTable(mirrors, preferred_mirrors) %}
-       </section>
-</div>
-{% end block %}
diff --git a/src/templates/mirrors/index.html b/src/templates/mirrors/index.html
new file mode 100644 (file)
index 0000000..02478ac
--- /dev/null
@@ -0,0 +1,34 @@
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Mirrors") }}{% end block %}
+
+{% block content %}
+       <section>
+               <div class="container">
+                       <div class="row">
+                               <div class="col col-lg-6">
+                                       <h1 class="display-2">{{ _("Mirrors") }}</h1>
+                               </div>
+                       </div>
+               </div>
+       </section>
+
+       <div class="row justify-content-center">
+               <div class="col-12 col-md-6">
+                       <div class="list-group">
+                               {% for m in mirrors %}
+                                       <a href="/mirrors/{{ m.hostname }}" class="list-group-item list-group-item-action
+                                                       list-group-item-{% if m.state == "UP" %}success{% elif m.state == "DOWN" %}danger{% else %}warning{% end %}
+                                                       flex-column align-items-start">
+                                               <h5 class="mb-1">{{ m.hostname }}</h5>
+
+                                               <p class="mb-0 text-truncate text-muted">
+                                                       <span class="flag-icon flag-icon-{{ m.country_code.lower() }} small mr-1"></span> {{ m.country_name }}
+                                                       {% if m.owner %}&dash; {{ m.owner }}{% end %}                                                   
+                                               </p>
+                                       </a>
+                               {% end %}
+                       </div>
+               </div>
+       </div>
+{% end block %}
diff --git a/src/templates/mirrors/mirror.html b/src/templates/mirrors/mirror.html
new file mode 100644 (file)
index 0000000..758d0be
--- /dev/null
@@ -0,0 +1,71 @@
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Mirror %s") % mirror }}{% end block %}
+
+{% block content %}
+       <section>
+               <div class="container">
+                       <h1 class="mb-0">{{ mirror }}</h1>
+
+                       {% if mirror.owner %}
+                               <p>{{ _("by %s") % mirror.owner }}</p>
+                       {% end %}
+               </div>
+       </section>
+
+       <div class="row justify-content-center">
+               <div class="col-12 col-md-6">
+                       <div class="card mb-4">
+                               {% if mirror.latitude and mirror.longitude %}
+                                       <div class="card-img-top">
+                                               {% module Map(mirror.latitude, mirror.longitude) %}
+                                       </div>
+                               {% end %}
+
+                               <div class="card-body">
+                                       <dl class="mb-0">
+                                               {% if mirror.asn %}
+                                                       <dt>{{ _("Autonomous System") }}</dt>
+                                                       <dd>{{ mirror.asn }}</dd>
+                                               {% end %}
+
+                                               <dt>{{ _("Country") }}</dt>
+                                               <dd>{{ mirror.country_name }}</dd>
+                                       </dl>
+                               </div>
+
+                               <ul class="list-group list-group-flush">
+                                       {% if mirror.state == "UP" %}
+                                               <li class="list-group-item list-group-item-success flex-column align-items-start">
+                                                       <p class="mb-1">{{ _("The mirror is up") }}</p>
+
+                                                       <small class="text-muted">
+                                                               {{ _("Last updated %s") % locale.format_date(mirror.last_update) }}
+                                                       </small>
+                                               </li>
+                                       {% elif mirror.state == "DOWN" %}
+                                               <li class="list-group-item list-group-item-danger flex-column align-items-start">
+                                                       <p class="mb-1">{{ _("The mirror is down") }}</p>
+
+                                                       <small class="text-muted">
+                                                               {{ _("Last updated %s") % locale.format_date(mirror.last_update) }}
+                                                       </small>
+                                               </li>
+                                       {% elif mirror.state == "OUTOFSYNC" %}
+                                               <li class="list-group-item list-group-item-warning flex-column align-items-start">
+                                                       <p class="mb-1">{{ _("The mirror is out of sync") }}</p>
+
+                                                       <small class="text-muted">
+                                                               {{ _("Last updated %s") % locale.format_date(mirror.last_update) }}
+                                                       </small>
+                                               </li>
+                                       {% end %}
+                               </ul>
+                       </div>
+
+                       <a class="btn btn-primary btn-block" href="{{ mirror.url }}">
+                               {{ _("Browse Mirror") }} <span class="fas fa-external-link-alt ml-2"></span>
+                       </a>
+               </div>
+       </div>
+{% end block %}
diff --git a/src/templates/modules/mirrors-table.html b/src/templates/modules/mirrors-table.html
deleted file mode 100644 (file)
index e46c570..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-<table class="table table-striped">
-       {% for mirror in mirrors %}
-               <tr>
-                       <td class="ac">
-                               {% if mirror.country_code %}
-                                       <img src="{{ static_url("images/flags/%s.png" % mirror.country_code.lower()) }}" alt="{{ mirror.country_code }}" />
-                                       <br>
-                                       {% if mirror.country_name %}
-                                               <abbr title="{{ mirror.country_name }}">{{ mirror.country_code }}</abbr>
-                                       {% else %}
-                                               {{ mirror.country_code }}
-                                       {% end %}
-                                       {% if mirror in preferred_mirrors %}*{% end %}
-                               {% end %}
-                       </td>
-
-                       {% if mirror.state == "UP" %}
-                               <td style="background-color: green;">
-                                       &nbsp;
-                               </td>
-                       {% elif mirror.state == "DOWN" %}
-                               <td style="background-color: red;">
-                                       &nbsp;
-                               </td>
-                       {% elif mirror.state == "OUTOFSYNC" %}
-                               <td style="background-color: yellow;">
-                                       &nbsp;
-                               </td>
-                       {% else %}
-                               <td style="background-color: grey;">
-                                       &nbsp; {{ mirror.state }}
-                               </td>
-                       {% end %}
-                       <td>
-                               {% if mirror.state in ("OUTOFSYNC", "DOWN") %}
-                                       <span class="text-error pull-right">
-                                               {{ _("Last update: %s") % locale.format_date(mirror.last_update, relative=True) }}
-                                       </span>
-                               {% end %}
-
-                               <a href="/mirror/{{ mirror.hostname }}">{{ mirror.hostname }}</a>
-                               <br>{{ mirror.owner }}
-                       </td>
-               </tr>
-       {% end %}
-</table>
index 796ae60388b74ffd9c83820c1c1f64e987834a42..f07059a0329a05004a94c22e9dd9e1b423994e45 100644 (file)
@@ -19,6 +19,7 @@ from . import boot
 from . import download
 from . import iuse
 from . import location
+from . import mirrors
 from . import newsletter
 from . import nopaste
 from . import people
@@ -81,8 +82,6 @@ class Application(tornado.web.Application):
                                # Old modules
                                "LanguageName"         : ui_modules.LanguageNameModule,
 
-                               "MirrorItem"           : ui_modules.MirrorItemModule,
-                               "MirrorsTable"         : ui_modules.MirrorsTableModule,
                                "ProgressBar"          : ui_modules.ProgressBarModule,
                                "FireinfoDeviceTable"  : ui_modules.FireinfoDeviceTableModule,
                                "FireinfoDeviceAndGroupsTable" : ui_modules.FireinfoDeviceAndGroupsTableModule,
@@ -165,8 +164,8 @@ class Application(tornado.web.Application):
 
                # mirrors.ipfire.org
                self.add_handlers(r"mirrors(\.dev)?\.ipfire\.org", [
-                       (r"/", MirrorIndexHandler),
-                       (r"/mirror/(.*)", MirrorItemHandler),
+                       (r"/", mirrors.IndexHandler),
+                       (r"/mirrors/(.*)", mirrors.MirrorHandler),
                ])
 
                # planet.ipfire.org
index b9dac89ca36f440f0ff7c0656199dd2c68c5901d..1d5b22d8e05c2ca3c5a4daae9a2aac3ab852d0ec 100644 (file)
@@ -7,7 +7,6 @@ import tornado.web
 from . import base
 
 from .handlers_fireinfo import *
-from .handlers_mirrors import *
 
 class LangCompatHandler(base.BaseHandler):
        """
diff --git a/src/web/handlers_mirrors.py b/src/web/handlers_mirrors.py
deleted file mode 100644 (file)
index b26abf0..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/python
-
-import socket
-import tornado.web
-
-from . import base
-
-class MirrorIndexHandler(base.BaseHandler):
-       def get(self):
-               ip_addr = self.get_argument("addr", None)
-               if not ip_addr:
-                       ip_addr = self.get_remote_ip()
-
-               location = self.geoip.get_location(ip_addr)
-
-               # Get a list of all mirrors.
-               mirrors = self.mirrors.get_all()
-
-               # Choose the preferred ones by their location.
-               preferred_mirrors = mirrors.get_for_location(location)
-
-               self.render("mirrors.html",
-                       preferred_mirrors=preferred_mirrors, mirrors=mirrors)
-
-
-class MirrorItemHandler(base.BaseHandler):
-       def get(self, what):
-               mirror = self.mirrors.get_by_hostname(what)
-               if not mirror:
-                       mirror = self.mirrors.get(what)
-
-               if not mirror:
-                       raise tornado.web.HTTPError(404, what)
-
-               ip_addr = self.get_argument("addr", None)
-               if not ip_addr:
-                       ip_addr = self.get_remote_ip()
-               client_location = self.geoip.get_location(ip_addr)
-
-               client_distance = mirror.distance_to(client_location, ignore_preference=True)
-
-               self.render("mirrors-item.html", item=mirror, client_distance=client_distance)
-
-
-class MirrorHandler(base.BaseHandler):
-       def get(self):
-               self.redirect("mirrors/all")
-
-
-class MirrorAllHandler(base.BaseHandler):
-       def get(self):
-               self.render("downloads-mirrors.html", mirrors=self.mirrors.list())
-
-
-class MirrorDetailHandler(base.BaseHandler):
-       def get(self, id):
-               self.render("download-mirror-detail.html", mirror=self.mirrors.get(id))
diff --git a/src/web/mirrors.py b/src/web/mirrors.py
new file mode 100644 (file)
index 0000000..9a83ef4
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/python
+
+import tornado.web
+
+from . import base
+
+class IndexHandler(base.BaseHandler):
+       def get(self):
+               self.render("mirrors/index.html", mirrors=self.backend.mirrors)
+
+
+class MirrorHandler(base.BaseHandler):
+       def get(self, hostname):
+               mirror = self.mirrors.get_by_hostname(hostname)
+               if not mirror:
+                       raise tornado.web.HTTPError(404, "Could not find %s" % hostname)
+
+               self.render("mirrors/mirror.html", mirror=mirror)
index b8acbd23be19ffe88ae1986252d6e597c0b6c523..6175e7327c4b32a56b1680519b57770a1b92977c 100644 (file)
@@ -100,17 +100,6 @@ class MapModule(UIModule):
                return self.render_string("modules/map.html", latitude=latitude, longitude=longitude)
 
 
-class MirrorItemModule(UIModule):
-       def render(self, item):
-               return self.render_string("modules/mirror-item.html", item=item)
-
-
-class MirrorsTableModule(UIModule):
-       def render(self, mirrors, preferred_mirrors=[]):
-               return self.render_string("modules/mirrors-table.html",
-                       mirrors=mirrors, preferred_mirrors=preferred_mirrors)
-
-
 class ProgressBarModule(UIModule):
        def render(self, value, colour=None):
                value *= 100