Compare commits
No commits in common. 'master' and 'legacy/0.9' have entirely different histories.
master
...
legacy/0.9
@ -1,47 +0,0 @@
|
||||
---
|
||||
kind: pipeline
|
||||
name: default
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
- name: publish
|
||||
pull: default
|
||||
image: plugins/docker:18.09
|
||||
settings:
|
||||
registry: https://registry.nixaid.com
|
||||
repo: "registry.nixaid.com/${DRONE_REPO_NAMESPACE}/${DRONE_REPO_NAME}"
|
||||
tags:
|
||||
- latest
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
# storage_path: /drone/docker
|
||||
# storage_driver: aufs
|
||||
# ipv6: false
|
||||
# debug: true
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
|
||||
- name: notify
|
||||
pull: default
|
||||
image: drillster/drone-email:latest
|
||||
settings:
|
||||
from: "Drone CI <noreply@nixaid.com>"
|
||||
host: mx.nixaid.com
|
||||
port: 587
|
||||
subject: "NIXAID Drone Pipeline {{#success build.status}}SUCCESS{{else}}FAILURE{{/success}} Notification"
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
status:
|
||||
- success
|
||||
- failure
|
@ -1,85 +0,0 @@
|
||||
# workspace:
|
||||
# base: /workspace
|
||||
# path: src/git.nixaid.com/arno/myapp/
|
||||
#
|
||||
# branches:
|
||||
# - master
|
||||
|
||||
pipeline:
|
||||
restore_cache:
|
||||
image: drillster/drone-volume-cache:latest
|
||||
restore: true
|
||||
mount:
|
||||
- /drone/docker
|
||||
# Set the ``DRONE_VOLUME=/tmp/drone-cache:/cache`` drone-server variable,
|
||||
# so you can benefit from the caching.
|
||||
# Otherwise you will have to make this repository trusted in Drone and use
|
||||
# the volumes as follows.
|
||||
# volumes:
|
||||
# - /tmp/drone-cache:/cache
|
||||
|
||||
# drone repo add arno/isso
|
||||
# drone secret add/update --name docker_username --value arno --event push --event tag --event deployment arno/isso
|
||||
# drone secret add/update --name docker_password --value "$(pass show vps/registry.nixaid.com | head -1)" --event push --event tag --event deployment arno/isso
|
||||
publish:
|
||||
image: plugins/docker:17.12
|
||||
# repo: andrey01/${DRONE_REPO_NAME}
|
||||
registry: registry.nixaid.com
|
||||
repo: registry.nixaid.com/arno/${DRONE_REPO_NAME}
|
||||
tags:
|
||||
- latest
|
||||
# - ${DRONE_COMMIT_SHA:0:7}
|
||||
# group: docker
|
||||
# dockerfile: Dockerfile
|
||||
secrets: [docker_username, docker_password]
|
||||
# Since we restore the docker image cache to /drone/docker
|
||||
storage_path: /drone/docker
|
||||
use_cache: true
|
||||
when:
|
||||
event: [push, tag]
|
||||
branch: master
|
||||
|
||||
rebuild_cache:
|
||||
image: drillster/drone-volume-cache:latest
|
||||
rebuild: true
|
||||
mount:
|
||||
- /drone/docker
|
||||
# Set the ``DRONE_VOLUME=/tmp/drone-cache:/cache`` drone-server variable,
|
||||
# so you can benefit from the caching.
|
||||
# Otherwise you will have to make this repository trusted in Drone and use
|
||||
# the volumes as follows.
|
||||
# volumes:
|
||||
# - /tmp/drone-cache:/cache
|
||||
|
||||
# # ca_cert comes from /srv/data/registry/certs/ca.crt
|
||||
# claircheck:
|
||||
# # image: jmccann/drone-clair:1
|
||||
# image: andrey01/drone-clair
|
||||
# url: http://clair:6060
|
||||
# secrets: [ docker_username, docker_password ]
|
||||
# # ignore errors for now. This will work only in drone 0.9 https://github.com/drone/drone-runtime/commit/3e8bd99f60f4032226523320cd2b2321f9525159
|
||||
# err_ignore: true
|
||||
# scan_image: registry.nixaid.com/arno/${DRONE_REPO_NAME}:latest
|
||||
# ca_cert: |
|
||||
# -----BEGIN CERTIFICATE-----
|
||||
# MIIBOjCB4KADAgECAgkAzhpbLWXa4H0wCgYIKoZIzj0EAwIwEDEOMAwGA1UEAwwF
|
||||
# bXktQ0EwHhcNMTgwNzA5MjIzMTAzWhcNMjgwNzA2MjIzMTAzWjAQMQ4wDAYDVQQD
|
||||
# DAVteS1DQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFIE8bTfQ76U5qG/Xgjw
|
||||
# BbQU0oRJLYlRxBIWF9MTNSJr2LoaoyrU8jrcWQGRrfKPoVuwUJWp2tp5SJy0AHH7
|
||||
# 4fijIzAhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgKkMAoGCCqGSM49
|
||||
# BAMCA0kAMEYCIQCYbTbxRD2yX4LzGjh84fKPWPQM9ps8RE2nfwZjqdRUGgIhAOHb
|
||||
# USigh6FzqEPk2jiaV3t1wNtChRWRfupTKG6CD345
|
||||
# -----END CERTIFICATE-----
|
||||
|
||||
notify:
|
||||
image: drillster/drone-email:latest
|
||||
from: Drone CI <noreply@nixaid.com>
|
||||
subject: NIXAID Drone Pipeline {{#success build.status}}SUCCESS{{else}}FAILURE{{/success}} Notification
|
||||
host: mx.nixaid.com
|
||||
port: 587
|
||||
# username: arno
|
||||
# secrets: [ email_username, email_password ]
|
||||
# recipients: [ andrey.arapov@nixaid.com ]
|
||||
when:
|
||||
status: [success, failure] # changed
|
||||
event: [push, tag]
|
@ -1,34 +0,0 @@
|
||||
# First, compile JS stuff
|
||||
FROM node:dubnium-buster
|
||||
WORKDIR /src/
|
||||
COPY . .
|
||||
RUN npm install -g requirejs uglify-js jade bower \
|
||||
&& make init js
|
||||
|
||||
# Second, create virtualenv
|
||||
FROM python:3.8-buster
|
||||
WORKDIR /src/
|
||||
COPY --from=0 /src .
|
||||
RUN python3 -m venv /isso \
|
||||
&& . /isso/bin/activate \
|
||||
&& pip3 install --no-cache-dir --upgrade pip \
|
||||
&& pip3 install --no-cache-dir gunicorn cffi flask \
|
||||
&& python setup.py install \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Third, create final repository
|
||||
FROM python:3.8-slim-buster
|
||||
WORKDIR /isso/
|
||||
COPY --from=1 /isso .
|
||||
|
||||
# Configuration
|
||||
VOLUME /db /config
|
||||
EXPOSE 8080
|
||||
ENV ISSO_SETTINGS /config/isso.cfg
|
||||
CMD ["/isso/bin/gunicorn", "-b", "0.0.0.0:8080", "-w", "4", "--preload", "isso.run", "--worker-tmp-dir", "/dev/shm"]
|
||||
|
||||
# Example of use:
|
||||
#
|
||||
# docker build -t isso .
|
||||
# docker run -it --rm -v /opt/isso:/config -v /opt/isso:/db -v $PWD:$PWD isso /isso/bin/isso -c \$ISSO_SETTINGS import disqus.xml
|
||||
# docker run -d --rm --name isso -p 8080:8080 -v /opt/isso:/config -v /opt/isso:/db isso
|
@ -1,65 +0,0 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
# This is the Vagrant config file for setting up an environment for Isso development.
|
||||
# It requires:
|
||||
#
|
||||
# * Vagrant (https://vagrantup.com)
|
||||
# * A VM engine, like VirtualBox (https://virtualbox.org)
|
||||
# * The Vagrant-Hostmanager plugin (https://github.com/smdahlen/vagrant-hostmanager)
|
||||
# * Ansible (https://www.ansible.com)
|
||||
#
|
||||
# With them installed, cd into this directory and do 'vagrant up'. It's possible Vagrant will
|
||||
# ask for your root password so it can update your /etc/hosts file. Once it's happily churning out
|
||||
# console output, go get a coffee :)
|
||||
#
|
||||
# The resulting VM should be accessible at http://isso-dev.local/ so you can try the demo page out.
|
||||
# Edit files in your checkout as usual. If you need to look at log files and stuff, 'vagrant ssh'
|
||||
# to get into the VM. Useful info about it:
|
||||
#
|
||||
# * Running Ubuntu 14.04
|
||||
# * Isso is running on uWSGI
|
||||
# * Actual webserver is Nginx to talk to uWSGI over a unix socket
|
||||
# * uWSGI log file is /var/log/uwsgi/apps/isso.log
|
||||
# * Isso DB file is /var/isso/comments.db
|
||||
# * Isso log file is /var/log/isso.log
|
||||
#
|
||||
# When the VM is getting rebooted vagrant mounts the shared folder after uWSGI is getting startet. To fix this issue for
|
||||
# the moment you need to 'vagrant ssh' into the VM and execute 'sudo service uwsgi restart'.
|
||||
#
|
||||
# For debugging with _pudb_ stop uWSGI service and start it manually
|
||||
# 'sudo uwsgi --ini /etc/uwsgi/apps-available/isso.ini'.
|
||||
#
|
||||
# Enjoy!
|
||||
|
||||
Vagrant.configure(2) do |config|
|
||||
|
||||
# The most common configuration options are documented and commented below.
|
||||
# For a complete reference, please see the online documentation at
|
||||
# https://docs.vagrantup.com.
|
||||
|
||||
config.vm.box = "ubuntu/trusty32"
|
||||
|
||||
config.vm.hostname = 'isso-dev.local'
|
||||
config.vm.network "private_network", type: "dhcp"
|
||||
|
||||
config.hostmanager.enabled = true
|
||||
config.hostmanager.manage_host = true
|
||||
config.hostmanager.ignore_private_ip = false
|
||||
config.hostmanager.include_offline = true
|
||||
config.hostmanager.ip_resolver = proc do |machine|
|
||||
result = ""
|
||||
machine.communicate.execute("ifconfig eth1") do |type, data|
|
||||
result << data if type == :stdout
|
||||
end
|
||||
(ip = /inet addr:(\d+\.\d+\.\d+\.\d)/.match(result)) && ip[1]
|
||||
end
|
||||
|
||||
config.vm.provision "ansible" do |ansible|
|
||||
ansible.playbook = "ansible/site.yml"
|
||||
ansible.limit = "all"
|
||||
ansible.verbose = "v"
|
||||
end
|
||||
|
||||
config.vm.post_up_message = "Browse to http://isso-dev.local/demo/index.html to start."
|
||||
end
|
@ -1,39 +0,0 @@
|
||||
user root;
|
||||
worker_processes 4;
|
||||
worker_rlimit_nofile 8192;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 2014;
|
||||
multi_accept on;
|
||||
use epoll;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
log_format timed '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for" '
|
||||
'$request_time $upstream_response_time $upstream_addr '
|
||||
' $upstream_status $upstream_cache_status $pipe';
|
||||
|
||||
access_log /var/log/nginx/access.log timed;
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
|
||||
keepalive_timeout 30;
|
||||
|
||||
gzip on;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
include /etc/nginx/sites-enabled/*;
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
server {
|
||||
client_max_body_size 20M;
|
||||
listen 80 default_server;
|
||||
server_name isso-dev.local;
|
||||
|
||||
root /vagrant/isso/demo;
|
||||
|
||||
location / {
|
||||
# uwsgi_pass unix:///run/uwsgi/app/isso/socket;
|
||||
uwsgi_pass 127.0.0.1:8080;
|
||||
include uwsgi_params;
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
[uwsgi]
|
||||
plugins = python
|
||||
|
||||
chdir = /vagrant
|
||||
|
||||
uid = root
|
||||
gid = root
|
||||
|
||||
socket = :8080
|
||||
|
||||
master = true
|
||||
processes = 4
|
||||
cache2 = name=hash,items=10240,blocksize=32
|
||||
spooler = /var/isso/spool
|
||||
module = isso.run
|
||||
env = ISSO_SETTINGS=/vagrant/share/isso-dev.conf
|
||||
env = PYTHON_EGG_CACHE=/tmp
|
||||
|
||||
# uncomment for debugging
|
||||
# daemonize = /var/log/uwsgi/uwsgi.log
|
||||
py-autoreload = 1
|
||||
|
||||
# prevent uWSGI from remapping stdin to /dev/null
|
||||
honour-stdin = true
|
@ -1,85 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Provision development server
|
||||
hosts: all
|
||||
sudo: true
|
||||
tasks:
|
||||
|
||||
- name: Apt | Add nodesource keys
|
||||
apt_key: url=https://deb.nodesource.com/gpgkey/nodesource.gpg.key state=present
|
||||
|
||||
- name: Apt | Add nodesource sources list deb
|
||||
apt_repository: repo='deb https://deb.nodesource.com/node {{ ansible_distribution_release }} main' state=present
|
||||
|
||||
- name: Apt | Add nodesource sources list deb src
|
||||
apt_repository: repo='deb-src https://deb.nodesource.com/node {{ ansible_distribution_release }} main' state=present
|
||||
|
||||
- name: Apt | Install packages
|
||||
apt: pkg={{ item }} state=latest update_cache=true
|
||||
with_items:
|
||||
- build-essential
|
||||
- curl
|
||||
- htop
|
||||
- vim
|
||||
- git
|
||||
- python-dev
|
||||
- python-software-properties
|
||||
- python-setuptools
|
||||
- python-pip
|
||||
- nginx
|
||||
- uwsgi
|
||||
- uwsgi-plugin-python
|
||||
- supervisor
|
||||
- sqlite3
|
||||
- nodejs
|
||||
- libffi-dev
|
||||
|
||||
- name: NPM | Install packages
|
||||
npm: name={{ item }} global=yes
|
||||
with_items:
|
||||
- bower
|
||||
- requirejs
|
||||
- uglify-js
|
||||
- jade
|
||||
|
||||
- name: Python | Install egg
|
||||
shell: cd /vagrant; python setup.py develop
|
||||
|
||||
- name: Make
|
||||
shell: cd /vagrant; {{ item }}
|
||||
with_items:
|
||||
- make init
|
||||
- make js
|
||||
|
||||
- name: Spool | Create directory
|
||||
file: path=/var/isso/spool state=directory mode=0777
|
||||
|
||||
- name: uwsgi | Deploy configuration
|
||||
copy: src=files/uwsgi.ini dest=/etc/uwsgi/apps-available/isso.ini
|
||||
|
||||
- name: uwsgi | Enable app
|
||||
file: src=/etc/uwsgi/apps-available/isso.ini dest=/etc/uwsgi/apps-enabled/isso.ini state=link
|
||||
|
||||
- name: uwsgi | Restart service daemon
|
||||
service: name=uwsgi state=restarted enabled=yes
|
||||
|
||||
- name: uwsgi | Chmod logfile
|
||||
file: path=/var/log/uwsgi/uwsgi.log state=touch mode="a+r"
|
||||
|
||||
- name: nginx | Deploy nginx.conf
|
||||
copy: src=files/nginx.conf dest=/etc/nginx/nginx.conf
|
||||
|
||||
- name: nginx | Delete default vhost
|
||||
action: file path=/etc/nginx/sites-enabled/default state=absent
|
||||
|
||||
- name: nginx | Deploy vhost config
|
||||
copy: src=files/nginx.vhost.conf dest=/etc/nginx/sites-available/isso.conf
|
||||
|
||||
- name: nginx | Enable vhost
|
||||
file: src=/etc/nginx/sites-available/isso.conf dest=/etc/nginx/sites-enabled/000-isso state=link
|
||||
|
||||
- name: nginx | Chmod logfile
|
||||
file: path=/var/log/nginx mode="a+rx" state=directory recurse=true
|
||||
|
||||
- name: nginx | Restart service daemon
|
||||
service: name=nginx state=restarted enabled=yes
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "isso",
|
||||
"description": "a Disqus alternative",
|
||||
"title": "isso API",
|
||||
"order": ["Thread", "Comment"],
|
||||
"template": {
|
||||
"withCompare": false
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,128 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2020 Lucas Cimon.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
"""Dump isso comments as text
|
||||
|
||||
The script can be run like this:
|
||||
|
||||
contrib/dump_comments.py .../path/to/isso.db --sort-by-last-reply
|
||||
|
||||
To get a list of all available options:
|
||||
|
||||
contrib/dump_comments.py --help
|
||||
|
||||
By installing the optional colorama dependency, you'll get a colored output.
|
||||
An example of output can be found at https://github.com/posativ/isso/issues/634
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sqlite3
|
||||
from collections import defaultdict, namedtuple
|
||||
from datetime import date
|
||||
from textwrap import indent
|
||||
|
||||
|
||||
class ColorFallback():
|
||||
__getattr__ = lambda self, name: '' # noqa: E731
|
||||
|
||||
|
||||
try:
|
||||
from colorama import Fore, Style, init
|
||||
init() # needed for Windows
|
||||
except ImportError: # fallback so that the imported classes always exist
|
||||
Fore = Style = ColorFallback()
|
||||
|
||||
|
||||
Comment = namedtuple('Comment', ('uri', 'id', 'parent', 'created', 'text', 'author', 'email', 'website', 'likes', 'dislikes', 'replies'))
|
||||
|
||||
INDENT = ' '
|
||||
QUERY = 'SELECT uri, comments.id, parent, created, text, author, email, website, likes, dislikes FROM comments INNER JOIN threads on comments.tid = threads.id'
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
if not args.colors:
|
||||
global Fore, Style
|
||||
Fore = Style = ColorFallback()
|
||||
db = sqlite3.connect(args.db_path)
|
||||
comments_per_uri = defaultdict(list)
|
||||
for result in db.execute(QUERY).fetchall():
|
||||
comment = Comment(*result, replies=[])
|
||||
comments_per_uri[comment.uri].append(comment)
|
||||
root_comments_per_sort_date = {}
|
||||
for comments in comments_per_uri.values():
|
||||
comments_per_id = {comment.id: comment for comment in comments}
|
||||
root_comments, sort_date = [], None
|
||||
for comment in comments:
|
||||
if comment.parent: # == this is a "reply" comment
|
||||
comments_per_id[comment.parent].replies.append(comment)
|
||||
if args.sort_by_last_reply and (sort_date is None or comment.created > sort_date):
|
||||
sort_date = comment.created
|
||||
else:
|
||||
root_comments.append(comment)
|
||||
if sort_date is None or comment.created > sort_date:
|
||||
sort_date = comment.created
|
||||
root_comments_per_sort_date[sort_date] = root_comments
|
||||
for _, root_comments in sorted(root_comments_per_sort_date.items(), key=lambda pair: pair[0]):
|
||||
print(Fore.MAGENTA + args.url_prefix + root_comments[0].uri + Fore.RESET)
|
||||
for comment in root_comments:
|
||||
print_comment(INDENT, comment)
|
||||
for comment in comment.replies:
|
||||
print_comment(INDENT * 2, comment)
|
||||
print()
|
||||
|
||||
|
||||
def print_comment(prefix, comment):
|
||||
author = comment.author or 'Anonymous'
|
||||
email = comment.email or ''
|
||||
website = comment.website or ''
|
||||
when = date.fromtimestamp(comment.created)
|
||||
popularity = ''
|
||||
if comment.likes:
|
||||
popularity = '+{.likes}'.format(comment)
|
||||
if comment.dislikes:
|
||||
if popularity:
|
||||
popularity += '/'
|
||||
popularity = '-{.dislikes}'.format(comment)
|
||||
print(prefix + '{Style.BRIGHT}{author}{Style.RESET_ALL} {Style.DIM}- {email} {website}{Style.RESET_ALL} {when} {Style.DIM}{popularity}{Style.RESET_ALL}'.format(Style=Style, **locals()))
|
||||
print(indent(comment.text, prefix))
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description='Dump all Isso comments in chronological order, grouped by replies',
|
||||
formatter_class=ArgparseHelpFormatter)
|
||||
parser.add_argument('db_path', help='File path to Isso Sqlite DB')
|
||||
parser.add_argument('--sort-by-last-reply', action='store_true', help='By default comments are sorted by "parent" comment date, this sort comments based on the last replies')
|
||||
parser.add_argument('--url-prefix', default='', help='Optional domain name to prefix to pages URLs')
|
||||
parser.add_argument('--no-colors', action='store_false', dest='colors', default=True, help='Disabled colored output')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
class ArgparseHelpFormatter(argparse.RawTextHelpFormatter, argparse.ArgumentDefaultsHelpFormatter):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -1,123 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
"""Comment importer from Blogger
|
||||
|
||||
This python script can convert comments posted to a Blogger-powered blog to a
|
||||
JSON file with can then be imported into Isso (by following the procedure
|
||||
explained in docs/docs/extras/advanced-migration.rst.
|
||||
|
||||
The script can be run like this:
|
||||
|
||||
python import_blogger.py -p 'http://myblog.com/' blogger.xml out.json
|
||||
|
||||
where `blogger.xml` is a dump of the blog produced by the Blogger platform, and
|
||||
the URL following the `-p` option is a prefix that will be applied to all post
|
||||
URLs: the original host will be stripped and the path will be appended to the
|
||||
string you specify here (this can be useful in the case that your blog moved to
|
||||
a different domain, subdomain, or just into a new directory).
|
||||
The `out.json` file is the file which will be generated by this tool, and which
|
||||
can then be fed into isso:
|
||||
|
||||
isso -c /path/to/isso.cfg import -t generic out.json
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import json
|
||||
|
||||
import feedparser
|
||||
import time
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
||||
class Post:
|
||||
def __init__(self, url):
|
||||
self.url = url
|
||||
self.title = None
|
||||
self.comments = []
|
||||
|
||||
def add_comment(self, comment):
|
||||
comment['id'] = len(self.comments) + 1
|
||||
self.comments.append(comment)
|
||||
|
||||
|
||||
def encode_post(post):
|
||||
ret = {}
|
||||
ret['id'] = post.url
|
||||
ret['title'] = post.title
|
||||
ret['comments'] = post.comments
|
||||
return ret
|
||||
|
||||
|
||||
class ImportBlogger:
|
||||
TYPE_COMMENT = 'http://schemas.google.com/blogger/2008/kind#comment'
|
||||
TYPE_POST = 'http://schemas.google.com/blogger/2008/kind#post'
|
||||
|
||||
def __init__(self, filename_in, filename_out, prefix):
|
||||
self.channel = feedparser.parse(filename_in)
|
||||
self.filename_out = filename_out
|
||||
self.prefix = prefix
|
||||
|
||||
def run(self):
|
||||
self.posts = {}
|
||||
for item in self.channel.entries:
|
||||
terms = [tag.term for tag in item.tags]
|
||||
if not terms:
|
||||
continue
|
||||
if terms[0] == self.TYPE_COMMENT:
|
||||
post = self.ensure_post(item)
|
||||
post.add_comment(self.process_comment(item))
|
||||
elif terms[0] == self.TYPE_POST:
|
||||
self.process_post(item)
|
||||
|
||||
data = [encode_post(p) for p in self.posts.values() if p.comments]
|
||||
with open(self.filename_out, 'w') as fp:
|
||||
json.dump(data, fp, indent=2)
|
||||
|
||||
def process_post(self, item):
|
||||
pid = self.post_id(item)
|
||||
if pid in self.posts:
|
||||
post = self.posts[pid]
|
||||
else:
|
||||
post = Post(pid)
|
||||
self.posts[pid] = post
|
||||
post.title = item.title
|
||||
|
||||
def ensure_post(self, item):
|
||||
pid = self.post_id(item)
|
||||
post = self.posts.get(pid, None)
|
||||
if not post:
|
||||
post = Post(pid)
|
||||
self.posts[pid] = post
|
||||
return post
|
||||
|
||||
def process_comment(self, item):
|
||||
comment = {}
|
||||
comment['author'] = item.author_detail.name
|
||||
comment['email'] = item.author_detail.email
|
||||
comment['website'] = item.author_detail.get('href', '')
|
||||
t = time.strftime('%Y-%m-%d %H:%M:%S', item.published_parsed)
|
||||
comment['created'] = t
|
||||
comment['text'] = item.content[0].value
|
||||
comment['remote_addr'] = '127.0.0.1'
|
||||
return comment
|
||||
|
||||
def post_id(self, item):
|
||||
u = urlparse(item.link)
|
||||
return self.prefix + u.path
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Convert comments from blogger.com')
|
||||
parser.add_argument('input', help='input file')
|
||||
parser.add_argument('output', help='output file')
|
||||
parser.add_argument('-p', dest='prefix',
|
||||
help='prefix to be added to paths (ID)',
|
||||
type=str, default='')
|
||||
args = parser.parse_args()
|
||||
|
||||
importer = ImportBlogger(args.input, args.output, args.prefix)
|
||||
importer.run()
|
@ -1,70 +0,0 @@
|
||||
Advanced Migration
|
||||
==================
|
||||
|
||||
In quickstart we saw you can import comments from Disqus or WordPress. But there
|
||||
are a many other comments system and you could be using one of them.
|
||||
|
||||
Isso provides a way to import such comments, however it's up to you to to:
|
||||
|
||||
- dump comments
|
||||
- fit the data to the following JSON format::
|
||||
|
||||
A list of threads, each item being a dict with the following data:
|
||||
|
||||
- id: a text representing the unique thread id (note: by default isso
|
||||
associates this ID to the article URL, but it can be changed on
|
||||
client side with "data-isso-id" - see :doc:`client configuration <../configuration/client>` )
|
||||
- title: the title of the thread
|
||||
- comments: the list of comments
|
||||
|
||||
Each item in that list of comments is a dict with the following data:
|
||||
|
||||
- id: an integer with the unique id of the comment inside the thread
|
||||
(it can be repeated among different threads); this will be used to
|
||||
order the comment inside the thread
|
||||
- author: the author's name
|
||||
- email: the author's email
|
||||
- website: the author's website
|
||||
- remote_addr: the author's IP
|
||||
- created: a timestamp, in the format "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
[
|
||||
{
|
||||
"id": "/blog/article1",
|
||||
"title": "First article!",
|
||||
"comments": [
|
||||
{
|
||||
"author": "James",
|
||||
"created": "2018-11-28 17:24:23",
|
||||
"email": "email@mail.com",
|
||||
"id": "1",
|
||||
"remote_addr": "127.0.0.1",
|
||||
"text": "Great article!",
|
||||
"website": "http://fefzfzef.frzr"
|
||||
},
|
||||
{
|
||||
"author": "Harold",
|
||||
"created": "2018-11-28 17:58:03",
|
||||
"email": "email2@mail.com",
|
||||
"id": "2",
|
||||
"remote_addr": "",
|
||||
"text": "I hated it...",
|
||||
"website": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
Keep in mind that isso expects to have an array, so keep the opening and ending square bracket even if you have only one article thread!
|
||||
|
||||
Next you can import you json dump:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
~> isso -c /path/to/isso.cfg import -t generic comment-dump.json
|
||||
[100%] 53 threads, 192 comments
|
||||
|
@ -1,20 +0,0 @@
|
||||
Community tools
|
||||
===============
|
||||
|
||||
Utility scripts
|
||||
---------------
|
||||
|
||||
Some utility scripts have been developed by isso users.
|
||||
They are stored in the `GitHub contrib/ directory
|
||||
<https://github.com/posativ/isso/tree/master/contrib>`_ :
|
||||
|
||||
* `dump_comments.py` : dump isso comments as text, optionally with color
|
||||
* `import_blogger.py` : comment importer from Blogger
|
||||
|
||||
|
||||
Related projects
|
||||
----------------
|
||||
|
||||
* `wonderfall/isso Docker image <https://github.com/Wonderfall/docker-isso>`
|
||||
* `a grav plugin to integrate isso comments <https://github.com/Sommerregen/grav-plugin-jscomments>`
|
||||
* `a Pelican theme supporting isso comments <https://github.com/Lucas-C/pelican-mg>`
|
@ -1,17 +1,32 @@
|
||||
Frequently asked question
|
||||
=========================
|
||||
|
||||
Why not use Gravatar/Libravatar/... ?
|
||||
-------------------------------------
|
||||
|
||||
Various people asked or complained about the generated icons next to their
|
||||
comments. First, it is not an avatar, it is an identicon used to
|
||||
*identify* an author of multiple comments without leaking personal
|
||||
informations (unlike Gravatar).
|
||||
|
||||
If you are in need of Gravatar_, then use Disqus. If you run your own
|
||||
Libravatar_ server, you can work on a patch for Isso which adds *optional*
|
||||
support for avatars.
|
||||
|
||||
.. _Gravatar: https://secure.gravatar.com/
|
||||
.. _Libravatar: http://libravatar.org/
|
||||
|
||||
Why SQLite3?
|
||||
------------
|
||||
|
||||
Although partially answered on the index page, here is a more complete answer: If
|
||||
Although partially answered on the index page, here a more complete answer: If
|
||||
you manage massive amounts of comments, Isso is a really bad choice. Isso is
|
||||
designed to be simple and easy to setup, it is not optimized for high-traffic
|
||||
designed to be simple and easy to setup, not optimizied for high-traffic
|
||||
websites (use a `dedicated Disqus`_ instance then).
|
||||
|
||||
Comments are not big data.
|
||||
comments are not big data
|
||||
|
||||
For example, if you have 209 threads and 778 comments in total this only needs 620 kilobytes
|
||||
of memory. This is an excellent use case for SQLite.
|
||||
For example, 209 threads and 778 comments in total only need 620K (kilobyte)
|
||||
memory. Excellent use case for SQLite.
|
||||
|
||||
.. _dedicated Disqus:
|
||||
|
@ -1,10 +0,0 @@
|
||||
Releasing steps
|
||||
===============
|
||||
|
||||
* Run ``python3 setup.py nosetests``, ``python2 setup.py nosetests``
|
||||
* Update version number in ``setup.py`` and ``CHANGES.rst``
|
||||
* ``git commit -m "Preparing ${VERSION}" setup.py CHANGES.rst``
|
||||
* ``git tag -as ${VERSION}``
|
||||
* ``make init all``
|
||||
* ``python3 setup.py sdist``
|
||||
* ``twine upload --sign dist/isso-${VERSION}.tar.gz``
|
@ -1,26 +1,28 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
try:
|
||||
text_type = unicode # Python 2
|
||||
string_types = (str, unicode)
|
||||
PY2K = True
|
||||
except NameError: # Python 3
|
||||
PY2K = False
|
||||
text_type = str
|
||||
string_types = (str, )
|
||||
import sys
|
||||
PY2K = sys.version_info[0] == 2
|
||||
|
||||
if not PY2K:
|
||||
buffer = memoryview
|
||||
filter, map, zip = filter, map, zip
|
||||
|
||||
def iteritems(dikt):
|
||||
return iter(dikt.items()) # noqa: E731
|
||||
map, zip, filter = map, zip, filter
|
||||
from functools import reduce
|
||||
|
||||
iteritems = lambda dikt: iter(dikt.items())
|
||||
|
||||
text_type = str
|
||||
string_types = (str, )
|
||||
|
||||
buffer = memoryview
|
||||
else:
|
||||
buffer = buffer
|
||||
from itertools import ifilter, imap, izip
|
||||
filter, map, zip = ifilter, imap, izip
|
||||
|
||||
def iteritems(dikt):
|
||||
return dikt.iteritems() # noqa: E731
|
||||
from itertools import imap, izip, ifilter
|
||||
map, zip, filter = imap, izip, ifilter
|
||||
reduce = reduce
|
||||
|
||||
iteritems = lambda dikt: dikt.iteritems()
|
||||
|
||||
text_type = unicode
|
||||
string_types = (str, unicode)
|
||||
|
||||
buffer = buffer
|
||||
|
@ -1,152 +0,0 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import re
|
||||
import logging
|
||||
import datetime
|
||||
|
||||
from email.utils import parseaddr, formataddr
|
||||
try:
|
||||
from backports.configparser import ConfigParser
|
||||
except ImportError:
|
||||
from configparser import ConfigParser
|
||||
|
||||
from isso.compat import text_type as str
|
||||
|
||||
logger = logging.getLogger("isso")
|
||||
|
||||
|
||||
def timedelta(string):
|
||||
"""
|
||||
Parse :param string: into :class:`datetime.timedelta`, you can use any
|
||||
(logical) combination of Nw, Nd, Nh and Nm, e.g. `1h30m` for 1 hour, 30
|
||||
minutes or `3w` for 3 weeks.
|
||||
|
||||
Raises a ValueError if the input is invalid/unparseable.
|
||||
|
||||
>>> print(timedelta("3w"))
|
||||
21 days, 0:00:00
|
||||
>>> print(timedelta("3w 12h 57m"))
|
||||
21 days, 12:57:00
|
||||
>>> print(timedelta("1h30m37s"))
|
||||
1:30:37
|
||||
>>> print(timedelta("1asdf3w"))
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: invalid human-readable timedelta
|
||||
"""
|
||||
|
||||
keys = ["weeks", "days", "hours", "minutes", "seconds"]
|
||||
regex = "".join(["((?P<%s>\\d+)%s ?)?" % (k, k[0]) for k in keys])
|
||||
kwargs = {}
|
||||
for k, v in re.match(regex, string).groupdict(default="0").items():
|
||||
kwargs[k] = int(v)
|
||||
|
||||
rv = datetime.timedelta(**kwargs)
|
||||
if rv == datetime.timedelta():
|
||||
raise ValueError("invalid human-readable timedelta")
|
||||
|
||||
return datetime.timedelta(**kwargs)
|
||||
|
||||
|
||||
class Section(object):
|
||||
"""A wrapper around :class:`IssoParser` that returns a partial configuration
|
||||
section object.
|
||||
|
||||
>>> conf = new({"foo": {"bar": "spam"}})
|
||||
>>> section = conf.section("foo")
|
||||
>>> conf.get("foo", "bar") == section.get("bar")
|
||||
True
|
||||
"""
|
||||
|
||||
def __init__(self, conf, section):
|
||||
self.conf = conf
|
||||
self.section = section
|
||||
|
||||
def get(self, key):
|
||||
return self.conf.get(self.section, key)
|
||||
|
||||
def getint(self, key):
|
||||
return self.conf.getint(self.section, key)
|
||||
|
||||
def getlist(self, key):
|
||||
return self.conf.getlist(self.section, key)
|
||||
|
||||
def getiter(self, key):
|
||||
return self.conf.getiter(self.section, key)
|
||||
|
||||
def getboolean(self, key):
|
||||
return self.conf.getboolean(self.section, key)
|
||||
|
||||
|
||||
class IssoParser(ConfigParser):
|
||||
"""Parse INI-style configuration with some modifications for Isso.
|
||||
|
||||
* parse human-readable timedelta such as "15m" as "15 minutes"
|
||||
* handle indented lines as "lists"
|
||||
"""
|
||||
|
||||
def getint(self, section, key):
|
||||
try:
|
||||
delta = timedelta(self.get(section, key))
|
||||
except ValueError:
|
||||
return super(IssoParser, self).getint(section, key)
|
||||
else:
|
||||
try:
|
||||
return int(delta.total_seconds())
|
||||
except AttributeError:
|
||||
return int(delta.total_seconds())
|
||||
|
||||
def getlist(self, section, key):
|
||||
return list(map(str.strip, self.get(section, key).split(',')))
|
||||
|
||||
def getiter(self, section, key):
|
||||
for item in map(str.strip, self.get(section, key).split('\n')):
|
||||
if item:
|
||||
yield item
|
||||
|
||||
def section(self, section):
|
||||
return Section(self, section)
|
||||
|
||||
|
||||
def new(options=None):
|
||||
|
||||
cp = IssoParser(allow_no_value=True)
|
||||
|
||||
if options:
|
||||
cp.read_dict(options)
|
||||
|
||||
return cp
|
||||
|
||||
|
||||
def load(default, user=None):
|
||||
|
||||
# return set of (section, option)
|
||||
def setify(cp):
|
||||
return set((section, option) for section in cp.sections()
|
||||
for option in cp.options(section))
|
||||
|
||||
parser = new()
|
||||
parser.read(default)
|
||||
|
||||
a = setify(parser)
|
||||
|
||||
if user:
|
||||
parser.read(user)
|
||||
|
||||
for item in setify(parser).difference(a):
|
||||
logger.warn("no such option: [%s] %s", *item)
|
||||
if item in (("server", "host"), ("server", "port")):
|
||||
logger.warn("use `listen = http://$host:$port` instead")
|
||||
if item == ("smtp", "ssl"):
|
||||
logger.warn("use `security = none | starttls | ssl` instead")
|
||||
if item == ("general", "session-key"):
|
||||
logger.info("Your `session-key` has been stored in the "
|
||||
"database itself, this option is now unused")
|
||||
|
||||
if not parseaddr(parser.get("smtp", "from"))[0]:
|
||||
parser.set("smtp", "from",
|
||||
formataddr(("Ich schrei sonst!", parser.get("smtp", "from"))))
|
||||
|
||||
return parser
|
@ -1,134 +0,0 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
}
|
||||
input {
|
||||
text-align: center;
|
||||
}
|
||||
.header::before, .header::after {
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
.header::after {
|
||||
clear: both;
|
||||
}
|
||||
.header::before, .header::after {
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
.header {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 68em;
|
||||
padding-bottom: 1em;
|
||||
padding-top: 1em;
|
||||
}
|
||||
.header header {
|
||||
display: block;
|
||||
float: left;
|
||||
font-weight: normal;
|
||||
margin-right: 16.0363%;
|
||||
width: 41.9818%;
|
||||
}
|
||||
.header header .logo {
|
||||
float: left;
|
||||
max-height: 60px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
.header header h1 {
|
||||
font-size: 1.55em;
|
||||
margin-bottom: 0.3em;
|
||||
}
|
||||
.header header h2 {
|
||||
font-size: 1.05em;
|
||||
}
|
||||
.header a, .header a:visited {
|
||||
color: #4d4c4c;
|
||||
text-decoration: none;
|
||||
}
|
||||
.outer {
|
||||
background-color: #eeeeee;
|
||||
box-shadow: 0 0 0.5em #c0c0c0 inset;
|
||||
}
|
||||
.outer .filters::before, .outer .filters::after {
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
.outer .filters::after {
|
||||
clear: both;
|
||||
}
|
||||
.outer .filters::before, .outer .filters::after {
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
.outer .filters {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 68em;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #4d4c4c;
|
||||
}
|
||||
.label {
|
||||
background-color: #ddd;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
cursor: pointer;
|
||||
line-height: 1.4em;
|
||||
outline: 0 none;
|
||||
padding: calc(0.6em - 1px);
|
||||
}
|
||||
.active {
|
||||
box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.6) inset;
|
||||
}
|
||||
.label-valid {
|
||||
background-color: #cfc;
|
||||
border-color: #cfc;
|
||||
}
|
||||
.label-pending {
|
||||
background-color: #ffc;
|
||||
border-color: #ffc;
|
||||
}
|
||||
.mode {
|
||||
float: left;
|
||||
}
|
||||
.pagination {
|
||||
float: right;
|
||||
}
|
||||
.note .label {
|
||||
margin: 9px;
|
||||
padding: 3px;
|
||||
}
|
||||
#login {
|
||||
margin-top: 40px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
.isso-comment-footer a {
|
||||
cursor: pointer;
|
||||
}
|
||||
.thread-title {
|
||||
margin-left: 3em;
|
||||
}
|
||||
.group {
|
||||
float: left;
|
||||
margin-left: 2em;
|
||||
}
|
||||
.editable {
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 5px;
|
||||
margin: 10px;
|
||||
padding: 5px;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
@ -1 +0,0 @@
|
||||
../share/isso.conf
|
Before Width: | Height: | Size: 11 KiB |
@ -1,100 +0,0 @@
|
||||
function ajax(req) {
|
||||
var r = new XMLHttpRequest();
|
||||
r.open(req.method, req.url, true);
|
||||
r.onreadystatechange = function () {
|
||||
if (r.readyState != 4 || r.status != 200) {
|
||||
if (req.failure) {
|
||||
req.failure();
|
||||
}
|
||||
return;
|
||||
}
|
||||
req.success(r.responseText);
|
||||
};
|
||||
r.send(req.data);
|
||||
}
|
||||
function fade(element) {
|
||||
var op = 1; // initial opacity
|
||||
var timer = setInterval(function () {
|
||||
if (op <= 0.1){
|
||||
clearInterval(timer);
|
||||
element.style.display = 'none';
|
||||
}
|
||||
element.style.opacity = op;
|
||||
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
|
||||
op -= op * 0.1;
|
||||
}, 10);
|
||||
}
|
||||
function moderate(com_id, hash, action, isso_host_script) {
|
||||
ajax({method: "POST",
|
||||
url: isso_host_script + "/id/" + com_id + "/" + action + "/" + hash,
|
||||
success: function(){
|
||||
fade(document.getElementById("isso-" + com_id));
|
||||
}});
|
||||
}
|
||||
function edit(com_id, hash, author, email, website, comment, isso_host_script) {
|
||||
ajax({method: "POST",
|
||||
url: isso_host_script + "/id/" + com_id + "/edit/" + hash,
|
||||
data: JSON.stringify({text: comment,
|
||||
author: author,
|
||||
email: email,
|
||||
website: website}),
|
||||
success: function(ret){
|
||||
console.log("edit successed: ", ret);// TODO display some pretty stuff & update msg
|
||||
},
|
||||
error: function(ret){
|
||||
console.log("Error: ", ret); // TODO flash msg/notif
|
||||
}});
|
||||
}
|
||||
function validate_com(com_id, hash, isso_host_script) {
|
||||
moderate(com_id, hash, "activate", isso_host_script);
|
||||
}
|
||||
function delete_com(com_id, hash, isso_host_script) {
|
||||
moderate(com_id, hash, "delete", isso_host_script);
|
||||
}
|
||||
function unset_editable(elt_id) {
|
||||
var elt = document.getElementById(elt_id);
|
||||
if (elt) {
|
||||
elt.contentEditable = false;
|
||||
elt.classList.remove("editable");
|
||||
}
|
||||
}
|
||||
function set_editable(elt_id) {
|
||||
var elt = document.getElementById(elt_id);
|
||||
if (elt) {
|
||||
elt.contentEditable = true;
|
||||
elt.classList.add("editable");
|
||||
}
|
||||
}
|
||||
function start_edit(com_id) {
|
||||
var editable_elements = ['isso-author-' + com_id,
|
||||
'isso-email-' + com_id,
|
||||
'isso-website-' + com_id,
|
||||
'isso-text-' + com_id];
|
||||
for (var idx=0; idx <= editable_elements.length; idx++) {
|
||||
set_editable(editable_elements[idx]);
|
||||
}
|
||||
document.getElementById('edit-btn-' + com_id).classList.toggle('hidden');
|
||||
document.getElementById('stop-edit-btn-' + com_id).classList.toggle('hidden');
|
||||
document.getElementById('send-edit-btn-' + com_id).classList.toggle('hidden');
|
||||
}
|
||||
function stop_edit(com_id) {
|
||||
var editable_elements = ['isso-author-' + com_id,
|
||||
'isso-email-' + com_id,
|
||||
'isso-website-' + com_id,
|
||||
'isso-text-' + com_id];
|
||||
for (var idx=0; idx <= editable_elements.length; idx++) {
|
||||
unset_editable(editable_elements[idx]);
|
||||
}
|
||||
document.getElementById('edit-btn-' + com_id).classList.toggle('hidden');
|
||||
document.getElementById('stop-edit-btn-' + com_id).classList.toggle('hidden');
|
||||
document.getElementById('send-edit-btn-' + com_id).classList.toggle('hidden');
|
||||
}
|
||||
function send_edit(com_id, hash, isso_host_script) {
|
||||
var author = document.getElementById('isso-author-' + com_id).textContent;
|
||||
var email = document.getElementById('isso-email-' + com_id).textContent;
|
||||
var website = document.getElementById('isso-website-' + com_id).textContent;
|
||||
var comment = document.getElementById('isso-text-' + com_id).textContent;
|
||||
edit(com_id, hash, author, email, website, comment, isso_host_script);
|
||||
stop_edit(com_id);
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Sem napiště svůj komentář (nejméně 3 znaky)",
|
||||
"postbox-author": "Jméno (nepovinné)",
|
||||
"postbox-email": "E-mail (nepovinný)",
|
||||
"postbox-website": "Web (nepovinný)",
|
||||
"postbox-preview": "Náhled",
|
||||
"postbox-edit": "Upravit",
|
||||
"postbox-submit": "Publikovat",
|
||||
"num-comments": "Jeden komentář\n{{ n }} Komentářů",
|
||||
"no-comments": "Zatím bez komentářů",
|
||||
"comment-reply": "Odpovědět",
|
||||
"comment-edit": "Upravit",
|
||||
"comment-save": "Uložit",
|
||||
"comment-delete": "Smazat",
|
||||
"comment-confirm": "Potvrdit",
|
||||
"comment-close": "Zavřít",
|
||||
"comment-cancel": "Zrušit",
|
||||
"comment-deleted": "Komentář smazán",
|
||||
"comment-queued": "Komentář ve frontě na schválení",
|
||||
"comment-anonymous": "Anonym",
|
||||
"comment-hidden": "{{ n }} skryto",
|
||||
"date-now": "právě teď",
|
||||
"date-minute": "před minutou\npřed {{ n }} minutami",
|
||||
"date-hour": "před hodinou\npřed {{ n }} hodinami",
|
||||
"date-day": "včera\npřed {{ n }} dny",
|
||||
"date-week": "minulý týden\npřed {{ n }} týdny",
|
||||
"date-month": "minulý měsíc\npřed {{ n }} měsíci",
|
||||
"date-year": "minulý rok\npřed {{ n }} lety"
|
||||
});
|
@ -1,32 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Type Comment Here (at least 3 chars)",
|
||||
"postbox-author": "Name (optional)",
|
||||
"postbox-email": "E-mail (optional)",
|
||||
"postbox-website": "Website (optional)",
|
||||
"postbox-preview": "Eksempel",
|
||||
"postbox-edit": "Rediger",
|
||||
"postbox-submit": "Submit",
|
||||
|
||||
"num-comments": "One Comment\n{{ n }} Comments",
|
||||
"no-comments": "Ingen kommentarer endnu",
|
||||
|
||||
"comment-reply": "Svar",
|
||||
"comment-edit": "Rediger",
|
||||
"comment-save": "Gem",
|
||||
"comment-delete": "Fjern",
|
||||
"comment-confirm": "Bekræft",
|
||||
"comment-close": "Luk",
|
||||
"comment-cancel": "Annuller",
|
||||
"comment-deleted": "Kommentar slettet.",
|
||||
"comment-queued": "Kommentar i kø for moderation.",
|
||||
"comment-anonymous": "Anonym",
|
||||
"comment-hidden": "{{ n }} Skjult",
|
||||
|
||||
"date-now": "lige nu",
|
||||
"date-minute": "et minut siden\n{{ n }} minutter siden",
|
||||
"date-hour": "en time siden\n{{ n }} timer siden",
|
||||
"date-day": "Igår\n{{ n }} dage siden",
|
||||
"date-week": "sidste uge\n{{ n }} uger siden",
|
||||
"date-month": "sidste måned\n{{ n }} måneder siden",
|
||||
"date-year": "sidste år\n{{ n }} år siden"
|
||||
});
|
@ -1,29 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Escriba su comentario aquí (al menos 3 caracteres)",
|
||||
"postbox-author": "Nombre (opcional)",
|
||||
"postbox-email": "E-mail (opcional)",
|
||||
"postbox-website": "Sitio web (opcional)",
|
||||
"postbox-preview": "Vista preliminar",
|
||||
"postbox-edit": "Editar",
|
||||
"postbox-submit": "Enviar",
|
||||
"num-comments": "Un Comentario\n{{ n }} Comentarios",
|
||||
"no-comments": "Sin Comentarios Todavía",
|
||||
"comment-reply": "Responder",
|
||||
"comment-edit": "Editar",
|
||||
"comment-save": "Guardar",
|
||||
"comment-delete": "Eliminar",
|
||||
"comment-confirm": "Confirmar",
|
||||
"comment-close": "Cerrar",
|
||||
"comment-cancel": "Cancelar",
|
||||
"comment-deleted": "Comentario eliminado.",
|
||||
"comment-queued": "Comentario en espera para moderación.",
|
||||
"comment-anonymous": "Anónimo",
|
||||
"comment-hidden": "{{ n }} Oculto(s)",
|
||||
"date-now": "ahora",
|
||||
"date-minute": "hace un minuto\nhace {{ n }} minutos",
|
||||
"date-hour": "hace una hora\nhace {{ n }} horas",
|
||||
"date-day": "ayer\nHace {{ n }} días",
|
||||
"date-week": "la semana pasada\nhace {{ n }} semanas",
|
||||
"date-month": "el mes pasado\nhace {{ n }} meses",
|
||||
"date-year": "el año pasado\nhace {{ n }} años"
|
||||
});
|
@ -1,32 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "نظر خود را اینجا بنویسید (حداقل سه نویسه)",
|
||||
"postbox-author": "اسم (اختیاری)",
|
||||
"postbox-email": "ایمیل (اختیاری)",
|
||||
"postbox-website": "سایت (اختیاری)",
|
||||
"postbox-preview": "پیشنمایش",
|
||||
"postbox-edit": "ویرایش",
|
||||
"postbox-submit": "ارسال",
|
||||
|
||||
"num-comments": "یک نظر\n{{ n }} نظر",
|
||||
"no-comments": "هنوز نظری نوشته نشده است",
|
||||
|
||||
"comment-reply": "پاسخ",
|
||||
"comment-edit": "ویرایش",
|
||||
"comment-save": "ذخیره",
|
||||
"comment-delete": "حذف",
|
||||
"comment-confirm": "تایید",
|
||||
"comment-close": "بستن",
|
||||
"comment-cancel": "انصراف",
|
||||
"comment-deleted": "نظر حذف شد.",
|
||||
"comment-queued": "نظر در صف بررسی مدیر قرار دارد.",
|
||||
"comment-anonymous": "ناشناس",
|
||||
"comment-hidden": "{{ n }} مخفی",
|
||||
|
||||
"date-now": "هم اکنون",
|
||||
"date-minute": "یک دقیقه پیش\n{{ n }} دقیقه پیش",
|
||||
"date-hour": "یک ساعت پیش\n{{ n }} ساعت پیش",
|
||||
"date-day": "دیروز\n{{ n }} روز پیش",
|
||||
"date-week": "یک هفته پیش\n{{ n }} هفته پیش",
|
||||
"date-month": "یک ماه پیش\n{{ n }} ماه پیش",
|
||||
"date-year": "یک سال پیش\n{{ n }} سال پیش"
|
||||
});
|
@ -1,32 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Kirjoita kommentti tähän (vähintään 3 merkkiä)",
|
||||
"postbox-author": "Nimi (valinnainen)",
|
||||
"postbox-email": "Sähköposti (valinnainen)",
|
||||
"postbox-website": "Web-sivu (valinnainen)",
|
||||
"postbox-preview": "Esikatselu",
|
||||
"postbox-edit": "Muokkaa",
|
||||
"postbox-submit": "Lähetä",
|
||||
|
||||
"num-comments": "Yksi kommentti\n{{ n }} kommenttia",
|
||||
"no-comments": "Ei vielä kommentteja",
|
||||
|
||||
"comment-reply": "Vastaa",
|
||||
"comment-edit": "Muokkaa",
|
||||
"comment-save": "Tallenna",
|
||||
"comment-delete": "Poista",
|
||||
"comment-confirm": "Vahvista",
|
||||
"comment-close": "Sulje",
|
||||
"comment-cancel": "Peru",
|
||||
"comment-deleted": "Kommentti on poistettu.",
|
||||
"comment-queued": "Kommentti on laitettu jonoon odottamaan moderointia.",
|
||||
"comment-anonymous": "Nimetön",
|
||||
"comment-hidden": "{{ n }} piilotettua",
|
||||
|
||||
"date-now": "hetki sitten",
|
||||
"date-minute": "minuutti sitten\n{{ n }} minuuttia sitten",
|
||||
"date-hour": "tunti sitten\n{{ n }} tuntia sitten",
|
||||
"date-day": "eilen\n{{ n }} päivää sitten",
|
||||
"date-week": "viime viikolla\n{{ n }} viikkoa sitten",
|
||||
"date-month": "viime kuussa\n{{ n }} kuukautta sitten",
|
||||
"date-year": "viime vuonna\n{{ n }} vuotta sitten"
|
||||
});
|
@ -1,29 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Napiši komentar ovdje (najmanje 3 znaka)",
|
||||
"postbox-author": "Ime (neobavezno)",
|
||||
"postbox-email": "E-mail (neobavezno)",
|
||||
"postbox-website": "Web stranica (neobavezno)",
|
||||
"postbox-preview": "Pregled",
|
||||
"postbox-edit": "Uredi",
|
||||
"postbox-submit": "Pošalji",
|
||||
"num-comments": "Jedan komentar\n{{ n }} komentara",
|
||||
"no-comments": "Još nema komentara",
|
||||
"comment-reply": "Odgovori",
|
||||
"comment-edit": "Uredi",
|
||||
"comment-save": "Spremi",
|
||||
"comment-delete": "Obriši",
|
||||
"comment-confirm": "Potvrdi",
|
||||
"comment-close": "Zatvori",
|
||||
"comment-cancel": "Odustani",
|
||||
"comment-deleted": "Komentar obrisan",
|
||||
"comment-queued": "Komentar u redu za provjeru.",
|
||||
"comment-anonymous": "Anonimno",
|
||||
"comment-hidden": "{{ n }} Skrivenih",
|
||||
"date-now": "upravo",
|
||||
"date-minute": "prije minutu\nprije {{ n }} minuta",
|
||||
"date-hour": "prije sat vremena\nprije {{ n }} sati",
|
||||
"date-day": "jučer\nprije {{ n }} dana",
|
||||
"date-week": "prošli tjedan\nprije {{ n }} tjedana",
|
||||
"date-month": "prošli mjesec\nprije {{ n }} mjeseci",
|
||||
"date-year": "prošle godine\nprije {{ n }} godina"
|
||||
});
|
@ -1,29 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Hozzászólást ide írd be (legalább 3 betűt)",
|
||||
"postbox-author": "Név (nem kötelező)",
|
||||
"postbox-email": "Email (nem kötelező)",
|
||||
"postbox-website": "Website (nem kötelező)",
|
||||
"postbox-preview": "Előnézet",
|
||||
"postbox-edit": "Szerekesztés",
|
||||
"postbox-submit": "Elküld",
|
||||
"num-comments": "Egy hozzászólás\n{{ n }} hozzászólás",
|
||||
"no-comments": "Eddig nincs hozzászólás",
|
||||
"comment-reply": "Válasz",
|
||||
"comment-edit": "Szerekesztés",
|
||||
"comment-save": "Mentés",
|
||||
"comment-delete": "Törlés",
|
||||
"comment-confirm": "Megerősít",
|
||||
"comment-close": "Bezár",
|
||||
"comment-cancel": "Törlés",
|
||||
"comment-deleted": "Hozzászólás törölve.",
|
||||
"comment-queued": "A hozzászólást előbb ellenőrizzük.",
|
||||
"comment-anonymous": "Névtelen",
|
||||
"comment-hidden": "{{ n }} rejtve",
|
||||
"date-now": "pillanatokkal ezelőtt",
|
||||
"date-minute": "egy perce\n{{ n }} perce",
|
||||
"date-hour": "egy órája\n{{ n }} órája",
|
||||
"date-day": "tegnap\n{{ n }} napja",
|
||||
"date-week": "múlt héten\n{{ n }} hete",
|
||||
"date-month": "múlt hónapban\n{{ n }} hónapja",
|
||||
"date-year": "tavaly\n{{ n }} éve"
|
||||
});
|
@ -1,29 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Typ reactie hier (minstens 3 karakters)",
|
||||
"postbox-author": "Naam (optioneel)",
|
||||
"postbox-email": "E-mail (optioneel)",
|
||||
"postbox-website": "Website (optioneel)",
|
||||
"postbox-preview": "Voorbeeld",
|
||||
"postbox-edit": "Bewerken",
|
||||
"postbox-submit": "Versturen",
|
||||
"num-comments": "Één reactie\n{{ n }} reacties",
|
||||
"no-comments": "Nog geen reacties",
|
||||
"comment-reply": "Beantwoorden",
|
||||
"comment-edit": "Bewerken",
|
||||
"comment-save": "Opslaan",
|
||||
"comment-delete": "Verwijderen",
|
||||
"comment-confirm": "Bevestigen",
|
||||
"comment-close": "Sluiten",
|
||||
"comment-cancel": "Annuleren",
|
||||
"comment-deleted": "Reactie verwijderd.",
|
||||
"comment-queued": "Reactie staat in de wachtrij voor goedkeuring.",
|
||||
"comment-anonymous": "Anoniem",
|
||||
"comment-hidden": "{{ n }} verborgen",
|
||||
"date-now": "zojuist",
|
||||
"date-minute": "een minuut geleden\n{{ n }} minuten geleden",
|
||||
"date-hour": "een uur geleden\n{{ n }} uur geleden",
|
||||
"date-day": "gisteren\n{{ n }} dagen geleden",
|
||||
"date-week": "vorige week\n{{ n }} weken geleden",
|
||||
"date-month": "vorige maand\n{{ n }} maanden geleden",
|
||||
"date-year": "vorig jaar\n{{ n }} jaar geleden"
|
||||
});
|
@ -1,34 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Escriure lo comentari aquí (almens 3 caractèrs)",
|
||||
"postbox-author": "Nom (opcional)",
|
||||
"postbox-email": "Corrièl (opcional)",
|
||||
"postbox-website": "Site web (opcional)",
|
||||
"postbox-preview": "Apercebut",
|
||||
"postbox-edit": "Modificar",
|
||||
"postbox-submit": "Enviar",
|
||||
"postbox-notification": "S'abonar per corrièl a las notificacions de responsas",
|
||||
|
||||
"num-comments": "Un comentari\n{{ n }} comentaris",
|
||||
"no-comments": "Cap de comentari pel moment",
|
||||
"atom-feed": "Flux Atom",
|
||||
|
||||
"comment-reply": "Respondre",
|
||||
"comment-edit": "Modificar",
|
||||
"comment-save": "Salvar",
|
||||
"comment-delete": "Suprimir",
|
||||
"comment-confirm": "Confirmar",
|
||||
"comment-close": "Tampar",
|
||||
"comment-cancel": "Anullar",
|
||||
"comment-deleted": "Comentari suprimit.",
|
||||
"comment-queued": "Comentari en espèra de moderacion.",
|
||||
"comment-anonymous": "Anonim",
|
||||
"comment-hidden": "1 rescondut\n{{ n }} resconduts",
|
||||
|
||||
"date-now": "ara meteis",
|
||||
"date-minute": "fa una minuta \nfa {{ n }} minutas",
|
||||
"date-hour": "fa una ora\nfa {{ n }} oras",
|
||||
"date-day": "Ièr\nfa {{ n }} jorns",
|
||||
"date-week": "la setmana passada\nfa {{ n }} setmanas",
|
||||
"date-month": "lo mes passat\nfa {{ n }} meses",
|
||||
"date-year": "l'an passat\nfa {{ n }} ans"
|
||||
});
|
@ -1,34 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Tutaj wpisz komentarz (co najmniej 3 znaki)",
|
||||
"postbox-author": "Imię/nick (opcjonalnie)",
|
||||
"postbox-email": "E-mail (opcjonalnie)",
|
||||
"postbox-website": "Strona (opcjonalnie)",
|
||||
"postbox-preview": "Podgląd",
|
||||
"postbox-edit": "Edytuj",
|
||||
"postbox-submit": "Wyślij",
|
||||
"postbox-notification": "Otrzymuj powiadomienia o odpowiedziach na e-mail",
|
||||
|
||||
"num-comments": "Jeden komentarz\n{{ n }} komentarze\n{{ n }} komentarzy",
|
||||
"no-comments": "Nie ma jeszcze komentarzy",
|
||||
"atom-feed": "Kanał Atom",
|
||||
|
||||
"comment-reply": "Odpowiedz",
|
||||
"comment-edit": "Edytuj",
|
||||
"comment-save": "Zapisz",
|
||||
"comment-delete": "Usuń",
|
||||
"comment-confirm": "Potwierdź",
|
||||
"comment-close": "Zamknij",
|
||||
"comment-cancel": "Anuluj",
|
||||
"comment-deleted": "Komentarz usunięty.",
|
||||
"comment-queued": "Komentarz w kolejce do moderacji.",
|
||||
"comment-anonymous": "Anonim",
|
||||
"comment-hidden": "{{ n }} ukryty\n{{ n }} ukryte\n{{ n }} ukrytych",
|
||||
|
||||
"date-now": "teraz",
|
||||
"date-minute": "minutę temu\n{{ n }} minuty temu\n{{ n }} minut temu",
|
||||
"date-hour": "godzinę temu\n{{ n }} godziny temu\n{{ n }} godzin temu",
|
||||
"date-day": "wczoraj\n{{ n }} dni temu",
|
||||
"date-week": "w ubiegłym tygodniu\n{{ n }} tygodnie temu\n{{ n }} tygodni temu",
|
||||
"date-month": "w ubiegłym miesiącu\n{{ n }} miesiące temu\n{{ n }} miesięcy temu",
|
||||
"date-year": "w ubiegłym roku\n{{ n }} lata temu\n{{ n }} lat temu"
|
||||
});
|
@ -1,34 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Digite seu comentário aqui (pelo menos 3 letras)",
|
||||
"postbox-author": "Nome (opcional)",
|
||||
"postbox-email": "E-mail (opcional)",
|
||||
"postbox-website": "Website (opcional)",
|
||||
"postbox-preview": "Prévia",
|
||||
"postbox-edit": "Editar",
|
||||
"postbox-submit": "Enviar",
|
||||
"postbox-notification": "Receber emails de notificação de respostas",
|
||||
|
||||
"num-comments": "Um Comentário\n{{ n }} Comentários",
|
||||
"no-comments": "Nenhum comentário ainda",
|
||||
"atom-feed": "Feed Atom",
|
||||
|
||||
"comment-reply": "Responder",
|
||||
"comment-edit": "Editar",
|
||||
"comment-save": "Salvar",
|
||||
"comment-delete": "Excluir",
|
||||
"comment-confirm": "Confirmar",
|
||||
"comment-close": "Fechar",
|
||||
"comment-cancel": "Cancelar",
|
||||
"comment-deleted": "Comentário apagado.",
|
||||
"comment-queued": "Comentário na fila de moderação.",
|
||||
"comment-anonymous": "Anônimo",
|
||||
"comment-hidden": "{{ n }} Oculto(s)",
|
||||
|
||||
"date-now": "agora mesmo",
|
||||
"date-minute": "um minuto atrás\n{{ n }} minutos atrás",
|
||||
"date-hour": "uma hora atrás\n{{ n }} horas atrás",
|
||||
"date-day": "ontem\n{{ n }} dias",
|
||||
"date-week": "semana passada\n{{ n }} semanas atrás",
|
||||
"date-month": "mês passado\n{{ n }} meses atrás",
|
||||
"date-year": "ano passado\n{{ n }} anos atrás"
|
||||
});
|
@ -1,29 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Sem napíšte svoj komentár (minimálne 3 znaky)",
|
||||
"postbox-author": "Meno (nepovinné)",
|
||||
"postbox-email": "E-mail (nepovinný)",
|
||||
"postbox-website": "Web (nepovinný)",
|
||||
"postbox-preview": "Náhľad",
|
||||
"postbox-edit": "Upraviť",
|
||||
"postbox-submit": "Publikovať",
|
||||
"num-comments": "Jeden komentár\n{{ n }} komentáre\n{{ n }} komentárov",
|
||||
"no-comments": "Zatiaľ bez komentárov",
|
||||
"comment-reply": "Odpovedať",
|
||||
"comment-edit": "Upraviť",
|
||||
"comment-save": "Uložiť",
|
||||
"comment-delete": "Zmazať",
|
||||
"comment-confirm": "Potvrdit",
|
||||
"comment-close": "Zavrieť",
|
||||
"comment-cancel": "Zrušiť",
|
||||
"comment-deleted": "Komentár bol vymazaný",
|
||||
"comment-queued": "Komentár zaradený na schválenie",
|
||||
"comment-anonymous": "Anonym",
|
||||
"comment-hidden": "{{ n }} skrytý\n{{ n }} skryté\n{{ n }} skrytých",
|
||||
"date-now": "práve teraz",
|
||||
"date-minute": "pred minútou\npred {{ n }} minútami",
|
||||
"date-hour": "pred hodinou\npred {{ n }} hodinami",
|
||||
"date-day": "včera\npred {{ n }} dňami",
|
||||
"date-week": "minulý týždeň\npred {{ n }} týždňami",
|
||||
"date-month": "minulý mesiac\npred {{ n }} mesiacmi",
|
||||
"date-year": "minulý rok\npred {{ n }} rokmi"
|
||||
});
|
@ -1,29 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Skriv din kommentar här (minst 3 tecken)",
|
||||
"postbox-author": "Namn (frivilligt)",
|
||||
"postbox-email": "E-mail (frivilligt)",
|
||||
"postbox-website": "Hemsida (frivilligt)",
|
||||
"postbox-preview": "Förhandsvisning",
|
||||
"postbox-edit": "Redigera",
|
||||
"postbox-submit": "Skicka",
|
||||
"num-comments": "En kommentar\n{{ n }} kommentarer",
|
||||
"no-comments": "Inga kommentarer än",
|
||||
"comment-reply": "Svara",
|
||||
"comment-edit": "Redigera",
|
||||
"comment-save": "Spara",
|
||||
"comment-delete": "Radera",
|
||||
"comment-confirm": "Bekräfta",
|
||||
"comment-close": "Stäng",
|
||||
"comment-cancel": "Avbryt",
|
||||
"comment-deleted": "Kommentar raderad.",
|
||||
"comment-queued": "Kommentaren inväntar granskning.",
|
||||
"comment-anonymous": "Anonym",
|
||||
"comment-hidden": "{{ n }} Gömd",
|
||||
"date-now": "just nu",
|
||||
"date-minute": "en minut sedan\n{{ n }} minuter sedan",
|
||||
"date-hour": "en timme sedan\n{{ n }} timmar sedan",
|
||||
"date-day": "igår\n{{ n }} dagar sedan",
|
||||
"date-week": "förra veckan\n{{ n }} veckor sedan",
|
||||
"date-month": "förra månaden\n{{ n }} månader sedan",
|
||||
"date-year": "förra året\n{{ n }} år sedan"
|
||||
});
|
@ -1,32 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "Nhập bình luận tại đây (tối thiểu 3 ký tự)",
|
||||
"postbox-author": "Tên (tùy chọn)",
|
||||
"postbox-email": "E-mail (tùy chọn)",
|
||||
"postbox-website": "Website (tùy chọn)",
|
||||
"postbox-preview": "Xem trước",
|
||||
"postbox-edit": "Sửa",
|
||||
"postbox-submit": "Gửi",
|
||||
|
||||
"num-comments": "Một bình luận\n{{ n }} bình luận",
|
||||
"no-comments": "Chưa có bình luận nào",
|
||||
|
||||
"comment-reply": "Trả lời",
|
||||
"comment-edit": "Sửa",
|
||||
"comment-save": "Lưu",
|
||||
"comment-delete": "Xóa",
|
||||
"comment-confirm": "Xác nhận",
|
||||
"comment-close": "Đóng",
|
||||
"comment-cancel": "Hủy",
|
||||
"comment-deleted": "Đã xóa bình luận.",
|
||||
"comment-queued": "Bình luận đang chờ duyệt",
|
||||
"comment-anonymous": "Nặc danh",
|
||||
"comment-hidden": "{{ n }} đã ẩn",
|
||||
|
||||
"date-now": "vừa mới",
|
||||
"date-minute": "một phút trước\n{{ n }} phút trước",
|
||||
"date-hour": "một giờ trước\n{{ n }} giờ trước",
|
||||
"date-day": "Hôm qua\n{{ n }} ngày trước",
|
||||
"date-week": "Tuần qua\n{{ n }} tuần trước",
|
||||
"date-month": "Tháng trước\n{{ n }} tháng trước",
|
||||
"date-year": "Năm trước\n{{ n }} năm trước"
|
||||
});
|
@ -1,33 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "在此输入评论 (最少 3 个字符)",
|
||||
"postbox-author": "名字 (可选)",
|
||||
"postbox-email": "电子邮箱 (可选)",
|
||||
"postbox-website": "网站 (可选)",
|
||||
"postbox-preview": "预览",
|
||||
"postbox-edit": "编辑",
|
||||
"postbox-submit": "提交",
|
||||
"postbox-notification": "有新回复时发送邮件通知",
|
||||
|
||||
"num-comments": "1 条评论\n{{ n }} 条评论",
|
||||
"no-comments": "还没有评论",
|
||||
|
||||
"comment-reply": "回复",
|
||||
"comment-edit": "编辑",
|
||||
"comment-save": "保存",
|
||||
"comment-delete": "删除",
|
||||
"comment-confirm": "确认",
|
||||
"comment-close": "关闭",
|
||||
"comment-cancel": "取消",
|
||||
"comment-deleted": "评论已删除.",
|
||||
"comment-queued": "评论待审核.",
|
||||
"comment-anonymous": "匿名",
|
||||
"comment-hidden": "{{ n }} 条评论已隐藏",
|
||||
|
||||
"date-now": "刚刚",
|
||||
"date-minute": "1 分钟前\n{{ n }} 分钟前",
|
||||
"date-hour": "1 小时前\n{{ n }} 小时前",
|
||||
"date-day": "昨天\n{{ n }} 天前",
|
||||
"date-week": "上周\n{{ n }} 周前",
|
||||
"date-month": "上个月\n{{ n }} 个月前",
|
||||
"date-year": "去年\n{{ n }} 年前"
|
||||
});
|
@ -1,33 +0,0 @@
|
||||
define({
|
||||
"postbox-text": "在此輸入留言 (至少 3 個字元)",
|
||||
"postbox-author": "名稱 (非必填)",
|
||||
"postbox-email": "電子信箱 (非必填)",
|
||||
"postbox-website": "個人網站 (非必填)",
|
||||
"postbox-preview": "預覽",
|
||||
"postbox-edit": "編輯",
|
||||
"postbox-submit": "送出",
|
||||
"postbox-notification": "訂閱回复的電子郵件通知",
|
||||
|
||||
"num-comments": "1 則留言\n{{ n }} 則留言",
|
||||
"no-comments": "尚無留言",
|
||||
|
||||
"comment-reply": "回覆",
|
||||
"comment-edit": "編輯",
|
||||
"comment-save": "儲存",
|
||||
"comment-delete": "刪除",
|
||||
"comment-confirm": "確認",
|
||||
"comment-close": "關閉",
|
||||
"comment-cancel": "取消",
|
||||
"comment-deleted": "留言已刪",
|
||||
"comment-queued": "留言待審",
|
||||
"comment-anonymous": "匿名",
|
||||
"comment-hidden": "{{ n }} 則隱藏留言",
|
||||
|
||||
"date-now": "剛剛",
|
||||
"date-minute": "1 分鐘前\n{{ n }} 分鐘前",
|
||||
"date-hour": "1 小時前\n{{ n }} 小時前",
|
||||
"date-day": "昨天\n{{ n }} 天前",
|
||||
"date-week": "上週\n{{ n }} 週前",
|
||||
"date-month": "上個月\n{{ n }} 個月前",
|
||||
"date-year": "去年\n{{ n }} 年前"
|
||||
});
|
@ -0,0 +1,50 @@
|
||||
define(["vendor/markup", "app/config", "app/i18n", "app/text/svg"], function(Mark, config, i18n, svg) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
// circumvent https://github.com/adammark/Markup.js/issues/22
|
||||
function merge(obj) {
|
||||
var result = {};
|
||||
for (var prefix in obj) {
|
||||
for (var attrname in obj[prefix]) {
|
||||
result[prefix + "-" + attrname] = obj[prefix][attrname];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Mark.delimiter = ":";
|
||||
Mark.includes = merge({
|
||||
conf: config,
|
||||
i18n: i18n[i18n.lang],
|
||||
svg: svg
|
||||
});
|
||||
|
||||
Mark.pipes.datetime = function(date) {
|
||||
if (typeof date !== "object") {
|
||||
date = new Date(parseInt(date, 10) * 1000);
|
||||
}
|
||||
|
||||
return [date.getUTCFullYear(), pad(date.getUTCMonth(), 2), pad(date.getUTCDay(), 2)].join("-");
|
||||
};
|
||||
|
||||
Mark.pipes.substract = function(a, b) {
|
||||
return parseInt(a, 10) - parseInt(b, 10);
|
||||
};
|
||||
|
||||
var strip = function(string) {
|
||||
// allow whitespace between Markup.js delimiters such as
|
||||
// {{ var | pipe : arg }} instead of {{var|pipe:arg}}
|
||||
return string.replace(/\{\{\s*(.+?)\s*\}\}/g, function(match, val) {
|
||||
return ("{{" + val + "}}").replace(/\s*\|\s*/g, "|")
|
||||
.replace(/\s*\:\s*/g, ":");
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
up: function(template, context) {
|
||||
return Mark.up(strip(template), context);
|
||||
}
|
||||
};
|
||||
});
|
@ -1,153 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Isso admin</title>
|
||||
<link type="text/css" href="{{isso_host_script}}/css/isso.css" rel="stylesheet">
|
||||
<link type="text/css" href="{{isso_host_script}}/css/admin.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="{{isso_host_script}}/js/admin.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<div class="header">
|
||||
<header>
|
||||
<img class="logo" src="{{isso_host_script}}/img/isso.svg" alt="Wynaut by @veekun"/>
|
||||
<div class="title">
|
||||
<a href="./">
|
||||
<h1>Isso</h1>
|
||||
<h2>Administration</h2>
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
<div class="outer">
|
||||
<div class="filters">
|
||||
<div class="mode">
|
||||
<a href="?mode=1&page={{page}}&order_by={{order_by}}">
|
||||
<span class="label label-valid {% if mode == 1 %}active{% endif %}">
|
||||
Valid ({{counts.get(1, 0)}})
|
||||
</span>
|
||||
</a>
|
||||
<a href="?mode=2&page={{page}}&order_by={{order_by}}">
|
||||
<span class="label label-pending {% if mode == 2 %}active{% endif %}">
|
||||
Pending ({{counts.get(2, 0)}})
|
||||
</span>
|
||||
</a>
|
||||
<a href="?mode=4&page={{page}}&order_by={{order_by}}">
|
||||
<span class="label label-staled {% if mode == 4 %}active{% endif %}">
|
||||
Staled ({{counts.get(4, 0)}})
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="group">
|
||||
Group by thread: <input type="checkbox" {% if order_by == "tid" %}checked{% endif %} onClick="javascript:window.location='?mode={{mode}}&page={{page}}&order_by={% if order_by == "tid" %}id{% else %}tid{% endif %}';" />
|
||||
</div>
|
||||
<div class="pagination">
|
||||
Pages:
|
||||
{% if page > 0 %}
|
||||
<a href="?mode={{mode}}&page={{page - 1}}">
|
||||
«
|
||||
</a>
|
||||
{% endif %}
|
||||
<input type="text" size="1" name="page" value="{{page}}" />
|
||||
{% if page < max_page %}
|
||||
<a href="?mode={{mode}}&page={{page + 1}}">
|
||||
»
|
||||
</a>
|
||||
{% endif %}
|
||||
/ {{ max_page }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="filters order">
|
||||
Order:
|
||||
{% for order in ['id', 'created', 'modified', 'likes', 'dislikes'] %}
|
||||
<a href="?mode={{mode}}&page={{page}}&order_by={{order}}&asc={{1 - asc}}">
|
||||
<span class="label label-valid {% if order == order_by %}active{% endif %}">
|
||||
{{ order }}
|
||||
{% if order == order_by %}
|
||||
{% if asc %} ↑ {% else %} ↓ {% endif %}
|
||||
{% else %}
|
||||
↓
|
||||
{% endif %}
|
||||
</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div id="isso-root">
|
||||
{% set thread_id = "no_id" %}
|
||||
{% for comment in comments %}
|
||||
{% if order_by == "tid" %}
|
||||
{% if thread_id != comment.tid %}
|
||||
{% set thread_id = comment.tid %}
|
||||
<h2 class="thread-title">{{comment.title}} (<a href="{{comment.uri}}">{{comment.uri}}</a>)</h2>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div class='isso-comment' id='isso-{{comment.id}}'>
|
||||
{% if conf.avatar %}
|
||||
<div class='avatar'>
|
||||
svg(data-hash='#{{comment.hash}}')
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class='text-wrapper'>
|
||||
<div class='isso-comment-header' role='meta'>
|
||||
{% if order_by != "tid" %}
|
||||
<div>Thread: {{comment.title}} (<a href="{{comment.uri}}">{{comment.uri}}</a>)</div><br />
|
||||
{% endif %}
|
||||
{% if comment.author %}
|
||||
<span class='author' id="isso-author-{{comment.id}}">{{comment.author}}</span>
|
||||
{% else %}
|
||||
<span class='author' id="isso-author-{{comment.id}}">Anonymous</span>
|
||||
{% endif %}
|
||||
{% if comment.email %}
|
||||
(<span id="isso-email-{{comment.id}}">{{comment.email}}</span> <a href="mailto:{{comment.email}}" rel='nofollow' class='email'>mailto</a>)
|
||||
{% else %}
|
||||
<span id="isso-email-{{comment.id}}"></span>
|
||||
{% endif %}
|
||||
{% if comment.website %}
|
||||
(<span id="isso-website-{{comment.id}}">{{comment.website}}</span> <a href="{{comment.website}}" rel='nofollow' class='website'>open</a>)
|
||||
{% else %}
|
||||
<span id="isso-website-{{comment.id}}"></span>
|
||||
{% endif %}
|
||||
<span class="spacer"> •</span>
|
||||
<time>{{comment.created | datetimeformat}}</time>
|
||||
<span class='note'>
|
||||
{% if comment.mode == 1 %}
|
||||
<span class="label label-valid">Valid</span>
|
||||
{% elif comment.mode == 2 %}
|
||||
<span class="label label-pending">Pending</span>
|
||||
{% elif comment.mode == 4 %}
|
||||
<span class="label label-staled">Staled</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
<div class='text'>
|
||||
{% if comment.mode == 4 %}
|
||||
<strong>HIDDEN</strong>. Original text: <br />
|
||||
{% endif %}
|
||||
<div id="isso-text-{{comment.id}}">{{comment.text}}</div>
|
||||
</div>
|
||||
<div class='isso-comment-footer'>
|
||||
{% if conf.votes and comment.likes - comment.dislikes != 0 %}
|
||||
<span class='votes'>{{comment.likes - comment.dislikes}}</span>
|
||||
{% endif %}
|
||||
<span class='spacer'></span>
|
||||
<a id="edit-btn-{{comment.id}}" class="edit" onClick="javascript:start_edit({{comment.id}})">Edit</a>
|
||||
<a id="stop-edit-btn-{{comment.id}}" class="hidden edit" onClick="javascript:stop_edit({{comment.id}})">Cancel</a>
|
||||
<a id="send-edit-btn-{{comment.id}}" class="hidden edit" onClick="javascript:send_edit({{comment.id}}, '{{comment.hash}}','{{isso_host_script}}')">Send</a>
|
||||
{% if comment.mode != 4 %}
|
||||
<a class="delete"
|
||||
onClick="javascript:delete_com({{comment.id}}, '{{comment.hash}}', '{{isso_host_script}}')">
|
||||
Delete
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if comment.mode == 2 %}
|
||||
<a class='validate'
|
||||
onClick="javascript:validate_com({{comment.id}}, '{{comment.hash}}', '{{isso_host_script}}')">Validate</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,28 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Isso admin</title>
|
||||
<link type="text/css" href="{{isso_host_script}}/css/isso.css" rel="stylesheet">
|
||||
<link type="text/css" href="{{isso_host_script}}/css/admin.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<div class="header">
|
||||
<header>
|
||||
<img class="logo" src="{{isso_host_script}}/img/isso.svg" alt="Wynaut by @veekun"/>
|
||||
<div class="title">
|
||||
<a href="./">
|
||||
<h1>Isso</h1>
|
||||
<h2>Administration</h2>
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
<main>
|
||||
<div id="disabled">
|
||||
Administration is disabled on this instance of isso. Set enabled=true
|
||||
in the admin section of your isso configuration to enable it.
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue