Git Product home page Git Product logo

cardshop's People

Contributors

dependabot[bot] avatar kelson42 avatar popolechien avatar rgaudin avatar tobaloidee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

cardshop's Issues

Interface crashes when selecting too many files

I had about 20 small files on my list and then clicked "update" and got this error log:
´´´

Request Method: GET
https://cardshop.hotspot.kiwix.org/configurations/2
2.1.2
KeyError
'tw'
./manager/templatetags/manager.py in , line 56
/usr/local/bin/uwsgi
3.6.6
['.', '', '/usr/local/lib/python36.zip', '/usr/local/lib/python3.6', '/usr/local/lib/python3.6/lib-dynload', '/usr/local/lib/python3.6/site-packages']
Thu, 18 Oct 2018 13:16:53 +0000

Error during template rendering
In template /app/manager/templates/base.html, error at line 0

1 {% load static %}
<title>{% block title %}Kiwix Hotspot Cardshop{% endblock %}</title> <style type="text/css">

Environment:

Request Method: GET
Request URL: https://cardshop.hotspot.kiwix.org/configurations/2

Django Version: 2.1.2
Python Version: 3.6.6
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'manager']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']

Template error:
In template /app/manager/templates/base.html, error at line 0
tw
1 : {% load static %}
2 :
3 :
4 : <title>{% block title %}Kiwix Hotspot Cardshop{% endblock %}</title>
5 :
6 :
7 :
8 :
9 :
10 : <style type="text/css">

Traceback:

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
34. response = get_response(request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
126. response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
124. response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/local/lib/python3.6/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
21. return view_func(request, *args, **kwargs)

File "./manager/views/config.py" in edit_configuration
145. return render(request, "edit_configuration.html", context)

File "/usr/local/lib/python3.6/site-packages/django/shortcuts.py" in render
36. content = loader.render_to_string(template_name, context, request, using=using)

File "/usr/local/lib/python3.6/site-packages/django/template/loader.py" in render_to_string
62. return template.render(context, request)

File "/usr/local/lib/python3.6/site-packages/django/template/backends/django.py" in render
61. return self.template.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render
171. return self._render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in _render
163. return self.nodelist.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render
937. bit = node.render_annotated(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render_annotated
904. return self.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py" in render
150. return compiled_parent._render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in _render
163. return self.nodelist.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render
937. bit = node.render_annotated(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render_annotated
904. return self.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py" in render
62. result = block.nodelist.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render
937. bit = node.render_annotated(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render_annotated
904. return self.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/defaulttags.py" in render
161. values = self.sequence.resolve(context, ignore_failures=True)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in resolve
698. new_obj = func(obj, *arg_vals)

File "./manager/templatetags/manager.py" in as_packages
56. for pid in json.loads(value) or []

File "./manager/templatetags/manager.py" in
56. for pid in json.loads(value) or []

Exception Type: KeyError at /configurations/2
Exception Value: 'tw'

GET
No GET data

POST
No POST data

FILES
No FILES data

COOKIES Variable Value
csrftoken 'w5RJuWtIrb9hlt0ZUqziB9wB6yxAbzRJVuArYUut27vppMalhD5oIqYecQVW8zbj'
sessionid 'ql9k2shu89s2xkfxa5ya9x8qqehibrm2'
messages ('b84a683202cb5027259b83e56e44d5e8171051b5$[["__json_message",0,25,"Configuration ' 'Updated successfuly !"]]')

META

Variable Value
CONTENT_LENGTH ''
CONTENT_TYPE ''
CSRF_COOKIE 'w5RJuWtIrb9hlt0ZUqziB9wB6yxAbzRJVuArYUut27vppMalhD5oIqYecQVW8zbj'
CSRF_COOKIE_USED True
DOCUMENT_ROOT '/etc/nginx/html'
HTTP_ACCEPT 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8'
HTTP_ACCEPT_ENCODING 'gzip, deflate, br'
HTTP_ACCEPT_LANGUAGE 'fr-CH,fr;q=0.9,en-CH;q=0.8,en;q=0.7,fr-FR;q=0.6,en-US;q=0.5'
HTTP_CACHE_CONTROL 'max-age=0'
HTTP_CONNECTION 'close'
HTTP_COOKIE ('csrftoken=w5RJuWtIrb9hlt0ZUqziB9wB6yxAbzRJVuArYUut27vppMalhD5oIqYecQVW8zbj; ' 'sessionid=ql9k2shu89s2xkfxa5ya9x8qqehibrm2; ' 'messages="b84a683202cb5027259b83e56e44d5e8171051b5$[[\"__json_message\"\0540\05425\054\"Configuration ' 'Updated successfuly !\"]]"')
HTTP_DNT '1'
HTTP_HOST 'cardshop.hotspot.kiwix.org'
HTTP_REFERER 'https://cardshop.hotspot.kiwix.org/configurations/2'
HTTP_UPGRADE_INSECURE_REQUESTS '1'
HTTP_USER_AGENT ('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, ' 'like Gecko) Chrome/69.0.3497.100 Safari/537.36')
HTTP_X_FORWARDED_FOR '62.220.153.85'
HTTP_X_FORWARDED_PORT '443'
HTTP_X_FORWARDED_PROTO 'https'
PATH_INFO '/configurations/2'
QUERY_STRING ''
REMOTE_ADDR '192.168.18.27'
REMOTE_PORT '58058'
REQUEST_METHOD 'GET'
REQUEST_SCHEME 'http'
REQUEST_URI '/configurations/2'
SCRIPT_NAME ''
SERVER_NAME ''
SERVER_PORT '80'
SERVER_PROTOCOL 'HTTP/1.1'
uwsgi.node b'manager.frontend.cardshop.kiwixoffline.node.intern'
uwsgi.version b'2.0.17.1'
wsgi.errors <_io.TextIOWrapper name=2 mode='w' encoding='UTF-8'>
wsgi.file_wrapper ''
wsgi.input <uwsgi._Input object at 0x7effcec087e0>
wsgi.multiprocess True
wsgi.multithread False
wsgi.run_once False
wsgi.url_scheme 'https'
wsgi.version (1, 0)

SETTINGS

Setting Value
ABSOLUTE_URL_OVERRIDES {}
ADMINS []
ADMIN_PASSWORD '********************'
ALLOWED_HOSTS ['*']
APPEND_SLASH True
AUTHENTICATION_BACKENDS ['django.contrib.auth.backends.ModelBackend']
AUTH_PASSWORD_VALIDATORS '********************'
AUTH_USER_MODEL 'auth.User'
BASE_DIR '/app'
CACHES {'default': {'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '/data/cache', 'OPTIONS': {'MAX_ENTRIES': 1000}, 'TIMEOUT': 86400}}
CACHE_MIDDLEWARE_ALIAS 'default'
CACHE_MIDDLEWARE_KEY_PREFIX '********************'
CACHE_MIDDLEWARE_SECONDS 600
CARDSHOP_API_URL '********************'
CONTENTS_FILE '/app/contents.json'
CSRF_COOKIE_AGE 31449600
CSRF_COOKIE_DOMAIN None
CSRF_COOKIE_HTTPONLY False
CSRF_COOKIE_NAME 'csrftoken'
CSRF_COOKIE_PATH '/'
CSRF_COOKIE_SAMESITE 'Lax'
CSRF_COOKIE_SECURE False
CSRF_FAILURE_VIEW 'django.views.csrf.csrf_failure'
CSRF_HEADER_NAME 'HTTP_X_CSRFTOKEN'
CSRF_TRUSTED_ORIGINS []
CSRF_USE_SESSIONS False
DATABASES {'default': {'ATOMIC_REQUESTS': False, 'AUTOCOMMIT': True, 'CONN_MAX_AGE': 0, 'ENGINE': 'django.db.backends.sqlite3', 'HOST': '', 'NAME': '/data/manager.sqlite3', 'OPTIONS': {}, 'PASSWORD': '********************', 'PORT': '', 'TEST': {'CHARSET': None, 'COLLATION': None, 'MIRROR': None, 'NAME': None}, 'TIME_ZONE': None, 'USER': ''}}
DATABASE_ROUTERS []
DATA_DIR '/data'
DATA_UPLOAD_MAX_MEMORY_SIZE 2621440
DATA_UPLOAD_MAX_NUMBER_FIELDS 1000
DATETIME_FORMAT 'N j, Y, P'
DATETIME_INPUT_FORMATS ['%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M:%S.%f', '%Y-%m-%d %H:%M', '%Y-%m-%d', '%m/%d/%Y %H:%M:%S', '%m/%d/%Y %H:%M:%S.%f', '%m/%d/%Y %H:%M', '%m/%d/%Y', '%m/%d/%y %H:%M:%S', '%m/%d/%y %H:%M:%S.%f', '%m/%d/%y %H:%M', '%m/%d/%y']
DATE_FORMAT 'N j, Y'
DATE_INPUT_FORMATS ['%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', '%b %d %Y', '%b %d, %Y', '%d %b %Y', '%d %b, %Y', '%B %d %Y', '%B %d, %Y', '%d %B %Y', '%d %B, %Y']
DEBUG True
DEBUG_PROPAGATE_EXCEPTIONS False
DECIMAL_SEPARATOR '.'
DEFAULT_CHARSET 'utf-8'
DEFAULT_CONTENT_TYPE 'text/html'
DEFAULT_EXCEPTION_REPORTER_FILTER 'django.views.debug.SafeExceptionReporterFilter'
DEFAULT_FILE_STORAGE 'django.core.files.storage.FileSystemStorage'
DEFAULT_FROM_EMAIL 'webmaster@localhost'
DEFAULT_INDEX_TABLESPACE ''
DEFAULT_TABLESPACE ''
DISALLOWED_USER_AGENTS []
EMAIL_BACKEND 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST 'localhost'
EMAIL_HOST_PASSWORD '********************'
EMAIL_HOST_USER ''
EMAIL_PORT 25
EMAIL_SSL_CERTFILE None
EMAIL_SSL_KEYFILE '********************'
EMAIL_SUBJECT_PREFIX '[Django] '
EMAIL_TIMEOUT None
EMAIL_USE_LOCALTIME False
EMAIL_USE_SSL False
EMAIL_USE_TLS False
FILE_CHARSET 'utf-8'
FILE_UPLOAD_DIRECTORY_PERMISSIONS None
FILE_UPLOAD_HANDLERS ['django.core.files.uploadhandler.MemoryFileUploadHandler', 'django.core.files.uploadhandler.TemporaryFileUploadHandler']
FILE_UPLOAD_MAX_MEMORY_SIZE 2621440
FILE_UPLOAD_PERMISSIONS None
FILE_UPLOAD_TEMP_DIR None
FIRST_DAY_OF_WEEK 0
FIXTURE_DIRS []
FORCE_SCRIPT_NAME None
FORMAT_MODULE_PATH None
FORM_RENDERER 'django.forms.renderers.DjangoTemplates'
IGNORABLE_404_URLS []
INSTALLED_APPS ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'manager']
INTERNAL_IPS []
LANGUAGES [('af', 'Afrikaans'), ('ar', 'Arabic'), ('ast', 'Asturian'), ('az', 'Azerbaijani'), ('bg', 'Bulgarian'), ('be', 'Belarusian'), ('bn', 'Bengali'), ('br', 'Breton'), ('bs', 'Bosnian'), ('ca', 'Catalan'), ('cs', 'Czech'), ('cy', 'Welsh'), ('da', 'Danish'), ('de', 'German'), ('dsb', 'Lower Sorbian'), ('el', 'Greek'), ('en', 'English'), ('en-au', 'Australian English'), ('en-gb', 'British English'), ('eo', 'Esperanto'), ('es', 'Spanish'), ('es-ar', 'Argentinian Spanish'), ('es-co', 'Colombian Spanish'), ('es-mx', 'Mexican Spanish'), ('es-ni', 'Nicaraguan Spanish'), ('es-ve', 'Venezuelan Spanish'), ('et', 'Estonian'), ('eu', 'Basque'), ('fa', 'Persian'), ('fi', 'Finnish'), ('fr', 'French'), ('fy', 'Frisian'), ('ga', 'Irish'), ('gd', 'Scottish Gaelic'), ('gl', 'Galician'), ('he', 'Hebrew'), ('hi', 'Hindi'), ('hr', 'Croatian'), ('hsb', 'Upper Sorbian'), ('hu', 'Hungarian'), ('ia', 'Interlingua'), ('id', 'Indonesian'), ('io', 'Ido'), ('is', 'Icelandic'), ('it', 'Italian'), ('ja', 'Japanese'), ('ka', 'Georgian'), ('kab', 'Kabyle'), ('kk', 'Kazakh'), ('km', 'Khmer'), ('kn', 'Kannada'), ('ko', 'Korean'), ('lb', 'Luxembourgish'), ('lt', 'Lithuanian'), ('lv', 'Latvian'), ('mk', 'Macedonian'), ('ml', 'Malayalam'), ('mn', 'Mongolian'), ('mr', 'Marathi'), ('my', 'Burmese'), ('nb', 'Norwegian Bokmål'), ('ne', 'Nepali'), ('nl', 'Dutch'), ('nn', 'Norwegian Nynorsk'), ('os', 'Ossetic'), ('pa', 'Punjabi'), ('pl', 'Polish'), ('pt', 'Portuguese'), ('pt-br', 'Brazilian Portuguese'), ('ro', 'Romanian'), ('ru', 'Russian'), ('sk', 'Slovak'), ('sl', 'Slovenian'), ('sq', 'Albanian'), ('sr', 'Serbian'), ('sr-latn', 'Serbian Latin'), ('sv', 'Swedish'), ('sw', 'Swahili'), ('ta', 'Tamil'), ('te', 'Telugu'), ('th', 'Thai'), ('tr', 'Turkish'), ('tt', 'Tatar'), ('udm', 'Udmurt'), ('uk', 'Ukrainian'), ('ur', 'Urdu'), ('vi', 'Vietnamese'), ('zh-hans', 'Simplified Chinese'), ('zh-hant', 'Traditional Chinese')]
LANGUAGES_BIDI ['he', 'ar', 'fa', 'ur']
LANGUAGE_CODE 'en-us'
LANGUAGE_COOKIE_AGE None
LANGUAGE_COOKIE_DOMAIN None
LANGUAGE_COOKIE_NAME 'django_language'
LANGUAGE_COOKIE_PATH '/'
LOCALE_PATHS []
LOGGING {'disable_existing_loggers': False, 'handlers': {'console': {'class': 'logging.StreamHandler'}}, 'loggers': {'django': {'handlers': ['console'], 'level': 'INFO'}, 'manager': {'handlers': ['console'], 'level': 'DEBUG'}}, 'version': 1}
LOGGING_CONFIG 'logging.config.dictConfig'
LOGIN_REDIRECT_URL '/'
LOGIN_URL '/login'
LOGOUT_REDIRECT_URL '/'
MANAGERS []
MANAGER_API_KEY '********************'
MANAGER_API_USERNAME '********************'
MEDIA_ROOT '/data/media'
MEDIA_URL '/media/'
MESSAGE_STORAGE 'django.contrib.messages.storage.fallback.FallbackStorage'
MIDDLEWARE ['django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware']
MIGRATION_MODULES {}
MIRROR 'http://download.kiwix.org'
MONTH_DAY_FORMAT 'F j'
NUMBER_GROUPING 0
PASSWORD_HASHERS '********************'
PASSWORD_RESET_TIMEOUT_DAYS '********************'
PREPEND_WWW False
ROOT_URLCONF 'manager.urls'
SECRET_KEY '********************'
SECURE_BROWSER_XSS_FILTER False
SECURE_CONTENT_TYPE_NOSNIFF False
SECURE_HSTS_INCLUDE_SUBDOMAINS False
SECURE_HSTS_PRELOAD False
SECURE_HSTS_SECONDS 0
SECURE_PROXY_SSL_HEADER None
SECURE_REDIRECT_EXEMPT []
SECURE_SSL_HOST None
SECURE_SSL_REDIRECT False
SERVER_EMAIL 'root@localhost'
SESSION_CACHE_ALIAS 'default'
SESSION_COOKIE_AGE 1209600
SESSION_COOKIE_DOMAIN None
SESSION_COOKIE_HTTPONLY True
SESSION_COOKIE_NAME 'sessionid'
SESSION_COOKIE_PATH '/'
SESSION_COOKIE_SAMESITE 'Lax'
SESSION_COOKIE_SECURE False
SESSION_ENGINE 'django.contrib.sessions.backends.db'
SESSION_EXPIRE_AT_BROWSER_CLOSE False
SESSION_FILE_PATH None
SESSION_SAVE_EVERY_REQUEST False
SESSION_SERIALIZER 'django.contrib.sessions.serializers.JSONSerializer'
SETTINGS_MODULE 'manager.settings'
SHORT_DATETIME_FORMAT 'm/d/Y P'
SHORT_DATE_FORMAT 'm/d/Y'
SIGNING_BACKEND 'django.core.signing.TimestampSigner'
SILENCED_SYSTEM_CHECKS []
STATICFILES_DIRS []
STATICFILES_FINDERS ['django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder']
STATICFILES_STORAGE 'django.contrib.staticfiles.storage.StaticFilesStorage'
STATIC_ROOT '/data/static'
STATIC_URL '/static/'
SUPPORT_EMAIL '[email protected]'
TEMPLATES [{'APP_DIRS': True, 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'OPTIONS': {'context_processors': ['django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages']}}]
TEST_NON_SERIALIZED_APPS []
TEST_RUNNER 'django.test.runner.DiscoverRunner'
THOUSAND_SEPARATOR ','
TIME_FORMAT 'P'
TIME_INPUT_FORMATS ['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
TIME_ZONE 'UTC'
USE_I18N True
USE_L10N True
USE_THOUSAND_SEPARATOR False
USE_TZ True
USE_X_FORWARDED_HOST False
USE_X_FORWARDED_PORT False
WSGI_APPLICATION 'manager.wsgi.application'
X_FRAME_OPTIONS 'SAMEORIGIN'
YEAR_MONTH_FORMAT 'F Y'

Order should not let me chose media size

It should by definition indicate the card's size - right now it let's me chose an 8Gb card for an 128Gb config. I don't see why/how the user should chose differently.
capture d ecran 2018-10-17 a 11 48 18

Missing notification that no address is available

Currently when trying to place an order and no address has been registered, this is not really indicated as a missing information in the Recipient field. Maybe circle it in red and/or add text "no delivery address available".

capture d ecran 2019-01-23 a 09 18 22

Landing page should be the config start page and have the current LP's wording

Related to #3 - I don't know if should be merged with this ticket or not, but basically I wasn't able to retrieve the page where my credits are listed (unless I logged out and then back in). So the top of the Config page, being where most people will want to start their journey, should have the current landing's wording.

Hi {{username}}!
Welcome to the Cardshop. Here you can freely import, design and export Kiwix Hotspot's presets (JSON files).

etc. etc.

Minor formatting issue on the welcome screen

Part of the text reads:
"Both option require you to pay a fee using a prepaid units system but obviously the virtual one is cheaper.

We don't need the superscript, or even the text in it - if people have access, they've paid the fee already and know what they got themselves into.

Error message about phone country code when inputing address is unclear

Added a local phone number without the country code and got a rather cryptic error message:
capture d ecran 2019-01-23 a 09 37 14

I suggest pre-filling the text field

  • country code + number or
  • +1 123 456 789 or
  • Simply replace the "Country" field with a "Country name/ code" dropdown (and invert country/email address fields so that it is right next to the phone number field)

Support Image-creation only

Following discussion with @Popolechien, we might want the shop to offer image-creation service instead of physical SD-card.

Difference with the current workflow would be:

  • No address
  • Order complete once image is uploaded by creator worker
  • Expiration of download link (a week ?)

Challenges:

  • Support this use case (work)
  • Blocks disk space for the duration of the download period on the warehouse
  • How would we charge for this ?

Defaultsort by name rather than size

And add a sorting option on top of each column so that people can either sort if by one or the other. I got confused thinking there was only one Wikipedia available in French and then only saw it much further down (same for WikiSource).
capture d ecran 2018-10-17 a 11 31 50

Send separate order confirmation receipts

(based on user feedback)

Currently upon ordering a card a single email is sent to

  1. The person who placed the order online (the Client)
  2. The person who is meant to receive it (the Recipient]

These may or may not be the same individual.

Here are the current text and fields being used:

Dear [Recipient],
Your order of 1 x 64GB Download with the [configuration's name] configuration on it has been accepted by the system.
You will be notified when it is ready for download.

Should you have any question, your contact for this transaction is [Client] (copied).
Order ID [some number with link to order details on cardshop]
Size: Card size (as opposite to content size)
Quantity: _number of units ordered, or 1 if download
Units: nn.d
Destination: (e.g. Recipient's address)
Cardshop contact Client's email address
Status: created, date/hour

To avoid confusion, this should be split in two messages:
Client message: (putting changes in Bold
"Success!
Your order of 1 x 64GB Download with the [configuration's name] configuration has been accepted by the system.
[Recipient] will be notified, and will get another message when it is ready for download.

Order summary:
Order ID [some number with link to order details on cardshop]
Size: Card size
Quantity: number of units ordered, or 1 if download
Unit cost: nn U (<- note: removed the decimal count in the number of units)
Destination: (e.g. Recipient's address)

You have XYZ units left on your account."

Recipient message
"Good news!
Client has placed an order for you on the Kiwix Cardshop. You will receive another message when the content is ready for shipping or download."

Sending Email from Sloppy is not working

Emails are essential to the scheduler as it is though emails that it communicates with its users: recipients, clients (person who orders on the website) and writer operators.

scheduler uses SMTP to connect to a mailbox [email protected] to send emails.

While this works locally, it doesn't work on Sloppy dues to Spam mitigation strategies (at Gandi but also at Gmail and probably any Email provider).

  • External IP is unpredictable (although it is safe to assume it's from their German provider)
  • Our external IP has-been/is/could-be listed in a RBL list of spamming IPs. We have no control over it and should it happen, our emails are rejected.
  • Our external IP does not follow anti-spam guidelines regarding reverse records resulting in rejects.

To circumvent this, I have added support for mailgun HTTP API as an alternative (used if MAILGUN_API_KEY env is specified) to SMTP.

Mailgun offers 10,000 emails/month with their free package (see pricing) and has a simple API. It's a dedicated service which handles emails correctly. Instructions to verify domains are easy and they have incoming email support (webhooks).

Amazon offers a similar service AWS SES but it seems the free 65K emails/months are only for apps hosted on AWS.

Way forward:

  • Create a Kiwix account on Mailgun
  • Follow DNS instructions for cardshop.hotspot.kiwix.org domain.
  • Share credentials/API key.

Popup does not clear after de-hovering

Use case: I generated a list, then removed some items. When the mouse hovers on the +/- symbol then the file name appears. In this case I removed bangla content and added english, but the mousehover text box did not clear properly (even when clicking randomly around the window).

As a quickfix, I would probably no show these text boxes in the first place.
capture d ecran 2018-10-17 a 10 58 52

Content package not listed

Added StackOverflow to my shopping cart but eventhough the size was added to the card, the item itself wasn't.
capture d ecran 2018-10-17 a 10 53 35

Addresses cannot be edited

Right now if I saved and made a mistake in my addressing I need to delete and re-create the entry. Simply add an edit button next to the delete one in the list of addresses.

Replace Quantity/Link validity dropdown by text form

The "Link validity" is not needed (it sounds rather greedy to triple the cost when tripling duration). Let's set a default to seven days (or 10, whatever), have it notified in the delivery email, and be done with it.

The Quantity dropdown could be replaced by a text field : it's easier to type 5 than dropdown>scroll down > select.

Change cardshop contact address

Contact should be hotspot at kiwix.org - I don't think a personal address makes much sense (roles and responsabilities evolve, people go on vacations) and it's easier to track and manage tickets like this on Freshdesk.

Pricing attributes

The current structure is 1Gb = 1 Unit. Hardware prices, however, are not linear: a quick benchmark on Amazon gave the following prices: 8 / 10 / 15 / 30 / 50 / 70 USD for 16/ 32/ 64/ 128/ 200 and 256 Gb, respectively, ie an 9x ratio between the smallest and biggest ones.

Prices will evolve but hopefully the ratio will remain within those boundaries. I would therefore attribute 2 Units to 16Gb cards (and below; if someone for some reason orders an empty-ish card, we still need to cover handling), then 3, 4, 8, 13 and 18 units.

On last config tab, replace Save with "Order card!"

Since this is the last step, Save is an option, but not the most likely one: users will probably want to close the deal and finalize their order. There should therefore be at least a "Next" button but most likely something more of a call to action, like "Order card!/"Place order"/"Confirm delivery address"

Also the Save/Next button(s) should be located under the Selected package list: if I'm looking at Afar then it's fine and not too far, but in English I'd have to scroll quite a bit before finding it.
capture d ecran 2018-10-17 a 11 03 04

Stackexchange zim files no correctly marked up

Probably related to #12 : when adding which ever stackexchange package to my selected contents, it does not move from the "available" to "selected" list, yet its weight is added to that of the card.

Too many duplicates

Looks like the library is not showing the last generated Stackexchange Zim files for a given topic, but all zims

capture d ecran 2018-10-18 a 15 06 33

Clearer order path is needed

Already mentioned in #37: basically the update button could work as "Next" and take the client from
General to Branding to Content to Address to Order (meaning that order and address should not only be as top right menu items but also as part of the Configuration tabs.
Alternatively, if for some reason this is too complex to implement, add a "Order!" button below "update configuration" on the Content tab.

Leave Country field blank on order form

When writing their address users have had to type pretty much everything already, so they can type their home country as well - also some browser will fill that field automatically from previous forms, it'll always be faster than looking for a specific country in a 200+ list.

Preview images in branding tab

Currently not sure it's the image I want.
Also, is there a suggested size (e.g. square), or minimum (50*50px)?

Question: do we really need a favicon? People might get confused as to what this is, and honestly it's not that important on a tab (case in point: the cardshop does not have a favicon). I'm not asking to remove it, but I wouldn't see a drawback to branding all tabs with a default Kiwix favicon.

How many use cases do we plan of people adding their own CSS? If the answer is "not many", I'd probably remove that option for the time being or, better, only have it appear on Admin accounts along with the favicon option (my understanding is that there will be admin accounts like mine and user accounts for FO end-users)

capture d ecran 2018-10-17 a 10 21 15

Reword "General" configuration tab

  • Project name
    -> Rename to "Hospot name" (otherwise we have two boxes next to one another with the word "name" in it, irrespective of explanations in field box. It also connects logically with the suggested "Kiwix hotspot" name);
    -> "Used to name your Box and its WiFi network" (missing network word);
  • Name (as in Configuration name): add star * and make sure this one is mandatory;
  • Region: there is a bit of French ("language en") and it should be clearer where that language will be applied, (e.g. "Hotspot interface language")
  • Timezone: add UTC/GMT values if possible
  • Security: are the admin/admin password fields mandatory if we install Aflatoun & co?
    capture d ecran 2018-10-17 a 10 10 41

Remove Version info from content selector

The version column indicates the date at which the zim file was generated: I see no added value to this info as:

  • People should not have a choice between the most recent and an older version of the zim file;
  • Since we do not update (yet) our zim file on a daily basis this lower the signaled value of our content by making it look stale.

Download email should not set font-color

I'm using Apple's desktop nightmore for my mail client and the download link appears black on black (I suspect that if the font color wasn't set it would work out fine?)
capture d ecran 2019-01-23 a 15 01 06

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.