Merge branch 'dev' into gh

This commit is contained in:
les 2021-03-26 22:27:41 +01:00
commit 9472d8d919
No known key found for this signature in database
GPG key ID: 352918250B012177
248 changed files with 19825 additions and 25482 deletions

3
.gitignore vendored
View file

@ -5,6 +5,9 @@ config/development.json
gancio_config.json
config.json
db.sqlite
thumb
docs/_site
.vscode
### Node template
# Logs

View file

@ -1,5 +1,93 @@
All notable changes to this project will be documented in this file.
### 0.24.0
- New Euskara language from Basque Country, thanks @hacklabkelo
- fix feed with filters
- cleaner homepage
- fix next/prev for recurrent events
- fix some history navigation issue
- fix blank lines in description
- upgrade deps
- better custom logo management
- fix settings update
### 0.23.0
- send AP Event Object instead of Note
- show only future unconfirmed events in admin panel
- new polish locale
- add friendly instances (an additional menu is shown)
- use user's logo not project's logo in federation
- start WPGancio plugin
- support media upload via url (API only)
- confirm before remove a resource
- confirm before remove a friendly instance
- event description supports some html tag
- fix redirect after login
### 0.22.0
- add admin announcement support (fix #74)
- each instance has a specific timezone you can choose from admin's panel
- refactoring language management (you can choose a default instance's language):
usually UX language is choosen looking at Accepted-Language header but there
are messages not generated from an http request (eg. sending events via AP).
In those cases a default instance's language is choosen (default 'en').
- use lazy loaded images
- better mobile experience for admins
- single day only recurring events
- fix user block in fediverse moderation
- filter and linkify content from fediverse
- add a lot of help strings in admin panel
- use html2text for event description in og: meta
- update deps
- fix a moment.js typo from/to issue
- fix #73
### 0.21.0
- a new recurring events logic (a la taskwarrior):
- each occurrence of a recurring event could be personalized.
- occurrence of recurring events are skippable.
- occurrence generation could be paused.
- support `h-event` microformats! in homepage and in any single event's page
- add a background task manager (email, recurring events creation)
- sanitize html content coming from fediverse and event description with dompurify
- also remove `fbclid` params in links
- front end search optimization
- use oauth2 for everything, password flow for webclient, this also fix
some issue with authentication
- clickable tags / places @ home (to add them as filters)
- use a cleaner menububble for the new editor
- add local smtp and sendmail options on configuration setup
- check permission for resource removal request from fediverse
- add resource from fediverse also when inReplyTo is another resource
- automatic API documentation inclusion in docs
- split moderation in another tab inside admin panel
- use axios instead of fetch everywhere
- lot of ux improvements & error handling
- search links in event description with linkifyjs while add/edit events
- remove text templates for emails and use html2text instead
- fix email unique index for users!
### 0.20.0
- New layout (navbar/footer/visible filters)
- two month calendar on large display
- admin could edit title, description, about, favicon & logo directly form admin panel
- new add event layout => https://demo.gancio.org/add
- new editor to describe events (bold, italic, link) supported also using copy/paste
- the editor also support live markdown (try using ### at line start)
- start oauth2 server implementation (documentation: https://gancio.org/dev/oauth)
- add fediverse moderation
- fix embedding an event via iframe
- images converted in .webp
- new catalan translation, thanks @fadelkon
### 0.17.14
- [locale] add catalan
- [fix] fedi outbox
### 0.17.12
- [ui] add admin section on event page in mobile #63
- [fix] remove username from users
### 0.17.11
- [refactor] s/fed_user/ap_user

61
assets/editor.less Normal file
View file

@ -0,0 +1,61 @@
.editor {
position: relative;
overflow-y: auto;
padding-top: 1.7em;
scrollbar-width: thin;
&.with-border {
border: 1px solid #ddd;
border-radius: 5px;
}
.content {
padding: 0px 5px 0px 5px;
flex: 1;
scrollbar-width: thin;
overflow-y: auto;
}
.menububble {
position: absolute;
display: flex;
overflow: hidden;
opacity: 0;
z-index: 1;
background: #dddddd;
transform: translateX(-50%);
border-radius: 3px;
padding: 0.07rem;
transition: opacity 0.2s, visibility 0.2s, left .2s, bottom .2s;
visibility: hidden;
&.is-active {
opacity: 1;
visibility: visible;
}
input {
padding: 0;
margin: 1px;
display: block;
border: 0;
color: #444;
font-size: .8em;
border-radius: 3px;
line-height: 100%;
transition: width .2s;
padding-left: 5px;
flex-grow: 1;
}
.fa-icon {
width: auto;
font-size: 10px;
height: 1.4em; /* or any other relative font sizes */
/* You would have to include the following two lines to make this work in Safari */
// max-width: 100%;
max-height: 100%;
}
}
}

56
assets/event.less Normal file
View file

@ -0,0 +1,56 @@
// .event {
// width: 320px;
// max-width: 450px;
// flex-grow: 1;
// margin: .2em;
// background-color: #202020;
// overflow: hidden;
// a:hover {
// text-decoration: none;
// .title {
// border-bottom: 1px solid #888;
// color: white;
// }
// }
// .title {
// margin-left: 1rem;
// margin-top: 1rem;
// margin-right: 1rem;
// border-bottom: 1px solid #333;
// transition: border-color .5s;
// font-size: 1.2em;
// max-height: 3em;
// overflow: hidden;
// color: white;
// font-weight: bold;
// }
// .card-footer {
// max-height: 4.5em;
// overflow: hidden;
// padding: .25rem 0.5rem;
// line-height: 1.8rem;
// min-height: 2.2rem;
// }
// .card-body {
// overflow: hidden;
// }
// .description {
// color: #999;
// font-size: 0.8em;
// overflow: hidden;
// max-height: 100%;
// }
// .el-image { width: 100% }
// img {
// width: 100%;
// max-height: 250px;
// object-fit: cover;
// object-position: top;
// }
// }

39
assets/helper.js Normal file
View file

@ -0,0 +1,39 @@
import take from 'lodash/take'
import get from 'lodash/get'
export function attributesFromEvents (_events, _tags) {
const colors = ['blue', 'orange', 'yellow', 'teal', 'indigo', 'green', 'red', 'purple', 'pink', 'gray']
const tags = take(_tags, 10).map(t => t.tag)
let attributes = []
attributes.push({ key: 'today', dates: new Date(), highlight: { color: 'green', fillMode: 'outline' } })
function getColor (event) {
const color = { class: 'vc-rounded-full', color: 'blue', fillMode: 'normal' }
const tag = get(event, 'tags[0]')
if (!tag) { return color }
const idx = tags.indexOf(tag)
if (idx < 0) { return color }
color.color = colors[idx]
return color
}
attributes = attributes.concat(_events
.filter(e => !e.multidate)
.map(e => {
return {
key: e.id,
dot: getColor(e),
dates: new Date(e.start_datetime * 1000)
}
}))
attributes = attributes.concat(_events
.filter(e => e.multidate)
.map(e => ({
key: e.id,
highlight: getColor(e),
dates: { start: new Date(e.start_datetime * 1000), end: new Date(e.end_datetime * 1000) }
})))
return attributes
}

View file

@ -1,116 +1,98 @@
@home_background: #222C32;
@background: white;
@success: #c7ffbc;
html, body {
scrollbar-width: thin;
overflow: auto !important;
scrollbar-color: #FF4511 #111;
font-family: sans-serif;
}
#__nuxt, #__layout {
height: 100%;
li {
margin-left: 10px;
}
.v-dialog .theme--dark.v-card {
background-color: #434343;
}
.v-application .p-description.text-body-1 {
letter-spacing: normal !important;
}
#home {
background-color: @home_background;
min-height: 100%;
max-width: 1400px;
padding-right: 0px;
overflow: hidden;
}
a, a:hover {
text-decoration: none;
#events {
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
html, body {
margin: 0px;
background-color: @background;
width: 100%;
height: 100%;
box-sizing: border-box;
font-family: BlinkMacSystemFont,-apple-system,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,Helvetica,Arial,sans-serif !important;
font-size: 15px;
.container {
max-width: 1400px;
}
* {
box-sizing: border-box;
.v-dialog {
width: 600px;
max-width: 800px;
}
.el-form-item {
margin-bottom: 5px;
.theme--dark.v-list {
background-color: #333;
}
.el-main {
max-width: 1000px;
border-radius: 0px;
margin: auto;
padding: 10px;
overflow: unset;
.v-autocomplete__content.v-menu__content {
scrollbar-width: thin;
scrollbar-color: #FF4511 #111;
}
.el-select-dropdown {
max-width: 100%;
left: 0px;
}
// EVENT
.event {
display: flex;
position: relative;
flex-direction: column;
width: 330px;
max-width: 500px;
flex-grow: 1;
margin-top: .4em;
margin-right: .4em;
overflow: hidden;
.page-enter-active, .page-leave-active {
transition: opacity .2s, transform .3s;
}
.page-enter, .page-leave-active {
transition: opacity .3s, transform .2s;
opacity: 0;
transform: translateX(30px);
}
pre {
font-family: BlinkMacSystemFont,-apple-system,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,Helvetica,Arial,sans-serif !important;
margin-bottom: 0px;
white-space: pre-line;
font-family: unset;
}
.el-popover {
word-break: normal;
}
.el-dialog {
z-index: 100;
max-width: 550px;
.el-dialog__body {
word-break: unset;
.title {
display: block;
max-height: 3.3em;
overflow: hidden;
margin: 0.5rem 1rem 0.5rem 1rem;
// color: white;
border-bottom: 1px solid rgba(4,4,4,0.2);
font-size: 1.2em !important;
line-height: 1.1em;
font-weight: 500;
}
.el-dialog__headerbtn {
font-size: 27px;
top: 9px;
right: 10px;
.el-dialog__close {
color: red;
// padding: 5px;
// background-color: #f0f0f0;
// border-radius: 22px;
// border: 1px solid #f0f0f0;
.body {
flex: 1 1 auto;
}
.img {
width: 100%;
max-height: 250px;
object-fit: cover;
object-position: top;
}
.place {
max-width: 100%;
span {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
p {
font-size: 16px;
a {
text-decoration: none;
}
}
.el-input__icon {
font-size: 20px;
}
@media only screen and (max-width: 768px) {
.el-dialog {
margin-top: 0px !important;
border-radius: 0px;
width: 100%;
}
html {
font-size: 13px;
}
.el-main {
margin-top: 0px !important;
border-radius: 0px;
padding: 5px;
}
.el-menu-item {
padding: 0px 17px;
}
}
}

View file

@ -0,0 +1,20 @@
<template lang="pug">
nuxt-link(:to='`/announcement/${announcement.id}`')
v-alert.mb-1(border='left' type='info' color="primary" show-icon) {{announcement.title}}
</template>
<script>
import { mapState } from 'vuex'
export default {
props: {
announcement: { type: Object, default: () => ({}) }
},
computed: {
...mapState(['announcements']),
description () {
return this.announcement.announcement.replace(/(<br>)+/g, '<br>')
}
}
}
</script>

View file

@ -1,107 +1,61 @@
<template lang="pug">
#calendar
v-calendar(
vc-calendar(
title-position='left'
:is-dark="settings['theme.is_dark']"
:columns="$screens({ sm: 2 }, 1)"
@update:from-page='updatePage'
:locale='$i18n.locale'
is-dark
:attributes='attributes'
:from-page.sync='page'
transition='fade'
is-expanded
is-inline
@dayclick='click')
</template>
<script>
import { mapState, mapActions, mapGetters } from 'vuex'
import moment from 'dayjs'
import { intersection, sample, take, get } from 'lodash'
import { mapState, mapActions } from 'vuex'
import dayjs from 'dayjs'
import { attributesFromEvents } from '../assets/helper'
export default {
name: 'Calendar',
props: {
events: { type: Array, default: () => [] }
},
data () {
const month = moment().month() + 1
const year = moment().year()
const month = dayjs().month() + 1
const year = dayjs().year()
return {
page: { month, year }
}
},
watch: {
// month selected
page () {
this.updateEvents(this.page)
computed: {
...mapState(['tags', 'filters', 'in_past', 'settings']),
attributes () {
return attributesFromEvents(this.events, this.tags)
}
},
methods: {
...mapActions(['updateEvents']),
...mapActions(['updateEvents', 'showPastEvents']),
updatePage (page) {
return new Promise((resolve, reject) => {
this.$emit('monthchange', page)
})
},
click (day) {
const element = document.getElementById(day.day)
if (element) { element.scrollIntoView() } // Even IE6 supports this
}
},
computed: {
...mapGetters(['filteredEventsWithPast']),
...mapState(['tags', 'filters', 'in_past']),
// TODO: could be better
attributes () {
const colors = ['green', 'orange', 'yellow', 'teal', 'indigo', 'blue', 'red', 'purple', 'pink', 'grey']
const tags = take(this.tags, 10).map(t => t.tag)
let attributes = []
attributes.push({ key: 'today', dates: new Date(), highlight: { color: 'green' } })
const that = this
function getColor (event) {
const color = { class: event.past && !that.filters.show_past_events && !that.in_past ? 'past-event vc-rounded-full' : 'vc-rounded-full', color: 'blue' }
const tag = get(event, 'tags[0]')
if (!tag) { return color }
const idx = tags.indexOf(tag)
if (idx < 0) { return color }
color.color = colors[idx]
return color
}
attributes = attributes.concat(this.filteredEventsWithPast
.filter(e => !e.multidate)
.map(e => {
const color = getColor(e)
return {
key: e.id,
dot: color,
dates: new Date(e.start_datetime * 1000)
}
}))
attributes = attributes.concat(this.filteredEventsWithPast
.filter(e => e.multidate)
.map(e => ({ key: e.id,
highlight: getColor(e),
dates: {
start: new Date(e.start_datetime * 1000), end: new Date(e.end_datetime * 1000) } })))
return attributes
this.$emit('dayclick', day)
}
}
}
</script>
<style>
#calendar {
margin: 0 auto;
max-width: 500px;
align-self: center;
}
.vc-opacity-0 {
opacity: 0.2 !important;
opacity: 0.3 !important;
}
/* .vc-highlight {
color: red;
height: 22px !important;
opacity: 0.4;
border-radius: 15px;
} */
.past-event {
opacity: 0.2;
opacity: 0.3;
}
</style>

84
components/Confirm.vue Normal file
View file

@ -0,0 +1,84 @@
<template lang="pug">
v-dialog(v-model='show'
:color='options.color'
:title='title'
:max-width='options.width'
:style="{ zIndex: options.zIndex, position: 'absolute' }"
@keydown.esc='cancel')
v-card
v-card-title {{ title }}
v-card-text(v-show='!!message') {{ message }}
v-card-actions
v-spacer
v-btn(color='error' @click='cancel') {{$t('common.cancel')}}
v-btn(color='primary' @click='agree') {{$t('common.ok')}}
</template>
<script>
/**
* Vuetify Confirm Dialog component
*
* Call it:
* this.$refs.confirm.open('Delete', 'Are you sure?', { color: 'red' }).then((confirm) => {})
*
* Or use await:
* if (await this.$refs.confirm.open('Delete', 'Are you sure?', { color: 'red' })) {
* // yes
* }
* else {
* // cancel
* }
*
*/
export default {
data: () => ({
dialog: false,
resolve: null,
reject: null,
message: null,
title: null,
options: {
color: 'danger',
width: 450,
zIndex: 500
}
}),
computed: {
show: {
get () {
return this.dialog
},
set (value) {
this.dialog = value
if (value === false) {
this.cancel()
}
}
}
},
created () {
this.$root.$confirm = this.open
},
methods: {
open (message, options = {}) {
this.dialog = true
this.title = options.title || this.$t('common.confirm')
this.message = this.$t(message, options)
this.options = Object.assign(this.options, options)
return new Promise((resolve, reject) => {
this.resolve = resolve
this.reject = reject
})
},
agree () {
this.resolve(true)
this.dialog = false
},
cancel () {
this.resolve(false)
this.dialog = false
}
}
}
</script>

319
components/Editor.vue Normal file
View file

@ -0,0 +1,319 @@
<template lang='pug'>
.editor.grey.darken-4(:class='focused')
.label {{label}}
editor-menu-bar.menubar.is-hidden(:editor='editor'
:keep-in-bounds='true' v-slot='{ commands, isActive, getMarkAttrs, focused }')
v-btn-toggle(dense)
v-btn(icon text tabindex='-1'
:class="{ primary: isActive.bold() }"
@click="commands.bold")
v-icon mdi-format-bold
v-btn(icon text tabindex='-1'
:class="{ primary: isActive.underline() }"
@click="commands.underline")
v-icon mdi-format-underline
v-btn(icon text tabindex='-1'
:class="{ primary: isActive.strike() }"
@click="commands.strike")
v-icon mdi-format-strikethrough-variant
v-btn(icon text tabindex='-1'
:class="{ primary: isActive.italic() }"
@click="commands.italic")
v-icon mdi-format-italic
v-btn(icon text tabindex='-1'
:class="{ primary: isActive.heading({level: 1}) }"
@click="commands.heading({level: 1})")
v-icon mdi-format-header-1
v-btn(icon text tabindex='-1'
:class="{ primary: isActive.heading({level: 2}) }"
@click="commands.heading({level: 2})")
v-icon mdi-format-header-2
v-btn(icon text tabindex='-1'
:class="{ primary: isActive.heading({level: 3}) }"
@click="commands.heading({level: 3})")
v-icon mdi-format-header-3
v-btn(icon text tabindex='-1'
:class="{ primary: isActive.code() }"
@click="commands.code")
v-icon mdi-code-tags
v-btn(icon text tabindex='-1'
:class="{ primary: isActive.blockquote() }"
@click="commands.blockquote")
v-icon mdi-format-quote-open
v-btn(icon text tabindex='-1'
:class="{ primary: isActive.bullet_list() }"
@click="commands.bullet_list")
v-icon mdi-format-list-bulleted
v-btn(icon text tabindex='-1' :class='{ primary: isActive.link() }'
@click='commands.link({href: getMarkAttrs("link") && getMarkAttrs("link").href ? "" : "https://"}); $refs.link.focus();')
v-icon mdi-link
v-text-field.pt-0.ml-1(v-show='isActive.link()' ref='link' @focus='focus' @blur='blur' hide-details
:value='isActive.link() && getMarkAttrs("link") && getMarkAttrs("link").href || ""'
@keypress.enter='commands.link({ href: $event.target.value}); editor.focus()')
editor-content.content(:editor='editor' spellcheck='false' :style="{ 'max-height': maxHeight }")
</template>
<script>
import debounce from 'lodash/debounce'
import { Editor, EditorContent, EditorMenuBar, EditorMenuBubble } from 'tiptap'
import {
Blockquote,
BulletList,
CodeBlock,
HardBreak,
Heading,
ListItem,
OrderedList,
Bold,
Code,
Italic,
Link,
History,
Strike,
Underline,
Placeholder
} from 'tiptap-extensions'
export default {
name: 'Editor',
components: { EditorContent, EditorMenuBar, EditorMenuBubble },
props: {
label: { type: String, default: 'Editor' },
value: { type: String, default: '' },
border: { type: Boolean, default: false },
noSave: { type: Boolean, default: false },
maxHeight: { type: String, Number, default: '' },
placeholder: { type: String, default: '' }
},
data () {
return {
options: [],
linkActive: false,
editor: null,
blurring: false,
update: false,
focused: ''
}
},
watch: {
value () {
if (this.update) {
this.update = false
return
}
this.editor.setContent(this.value)
}
},
mounted () {
this.editor = new Editor({
onFocus: () => this.focus(),
onBlur: () => this.blur(),
onUpdate: debounce(({ getHTML }) => {
this.update = true
this.$emit('input', getHTML())
}, 1000),
content: this.value,
extensions: [
new Blockquote(),
new BulletList(),
new CodeBlock(),
new HardBreak(),
new Heading({ levels: [1, 2, 3, 4, 5, 6] }),
new OrderedList(),
new ListItem(),
new Code(),
new History(),
new Link({ openOnClick: false, target: '_blank' }),
new Bold(),
new Italic(),
new Strike(),
new Underline(),
new Placeholder({
emptyEditorClass: 'is-editor-empty',
emptyNodeClass: 'is-empty',
emptyNodeText: this.placeholder,
showOnlyWhenEditable: true,
showOnlyCurrent: true
})
]
})
},
beforeDestroy () {
if (this.editor) { this.editor.destroy() }
},
methods: {
blur () {
this.blurring = true
window.setTimeout(() => {
if (this.blurring) {
this.focused = ''
this.blurring = false
}
}, 200)
},
focus () {
this.focused = 'editor--focused'
this.$nextTick(() => {
this.blurring = false
})
}
}
}
</script>
<style lang='less'>
.editor {
margin-top: 4px;
padding-top: 12px;
padding-bottom: 22px;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: #FF4500 transparent;
scroll-behavior: smooth;
font-family: sans-serif;
font-size: 1.1em;
.editor p.is-editor-empty:first-child::before {
content: attr(data-empty-text);
float: left;
color: #aaa;
// opacity: .4;
pointer-events: none;
height: 0;
font-style: italic;
}
.label {
left: 0px;
position: relative;
transform-origin: top left;
transition: transform .3s, scale .3s, color .3s;
transform: translateY(20px);
}
&.editor--focused {
.label {
color: #FF4500;
transform: translateY(0px) scale(0.75);
}
.menubar {
opacity: 1 !important;
}
.ProseMirror::after {
width : 100% !important;
transform: scaleX(1) !important;
}
}
.menubar {
transition: opacity .5s;
opacity: 0;
// position: absolute;
}
.focused .ProseMirror::after {
width: 100%;
}
.ProseMirror {
padding: 15px;
outline: 0;
&::before {
bottom: 0px;
content: "";
left: 0;
position: absolute;
transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1);
width: 100%;
border-width: thin 0 0 0;
border-style: solid;
height: 0px;
border-color: rgba(255, 255, 255, 0.7);
}
&::after {
bottom: 0px;
content: "";
left: 0;
position: absolute;
height: 0px;
transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1);
width: 100%;
border-width: 2px 0 0 0;
border-style: solid;
border-color: #FF4500;
transform: scaleX(0);
}
}
}
// position: relative;
// overflow-y: auto;
// padding-top: 1.7em;
// &.with-border {
// border: 1px solid #ddd;
// border-radius: 5px;
// }
// .content {
// padding: 0px 5px 0px 5px;
// flex: 1;
// scrollbar-width: thin;
// overflow-y: auto;
// }
// .menububble {
// position: absolute;
// display: flex;
// overflow: hidden;
// opacity: 0;
// z-index: 1;
// background: #dddddd;
// transform: translateX(-50%);
// border-radius: 3px;
// padding: 0.07rem;
// transition: opacity 0.2s, visibility 0.2s, left .2s, bottom .2s;
// visibility: hidden;
// &.is-active {
// opacity: 1;
// visibility: visible;
// }
// input {
// padding: 0;
// margin: 1px;
// display: block;
// border: 0;
// color: #444;
// font-size: .8em;
// border-radius: 3px;
// line-height: 100%;
// transition: width .2s;
// padding-left: 5px;
// flex-grow: 1;
// }
// .fa-icon {
// width: auto;
// font-size: 10px;
// height: 1.4em; /* or any other relative font sizes */
// /* You would have to include the following two lines to make this work in Safari */
// // max-width: 100%;
// max-height: 100%;
// }
// }
// }
</style>

View file

@ -1,132 +1,46 @@
<template lang="pug">
nuxt-link.event(:to='`/event/${link}`' :class='{ withImg: event.image_path }')
v-card.h-event.event
nuxt-link(:to='`/event/${event.id}`')
v-img.img(:src="`/media/thumb/${event.image_path || 'logo.svg' }`")
v-icon.float-right.mr-1(v-if='event.parentId' color='success') mdi-repeat
.title.p-name {{event.title}}
//- image
img(v-if='showImage && event.image_path' :src='`/media/thumb/${event.image_path}`')
v-card-text.body.pt-0.pb-0
time.dt-start.subtitle-1(:datetime='event.start_datetime|unixFormat("YYYY-MM-DD HH:mm")') <v-icon>mdi-calendar</v-icon> {{ event|when }}
.d-none.dt-end {{event.end_datetime|unixFormat('YYYY-MM-DD HH:mm')}}
a.place.d-block.p-location.pl-0(text color='primary' @click="$emit('placeclick', event.place.id)") <v-icon>mdi-map-marker</v-icon> {{event.place.name}}
.event-info
.content-info
v-card-actions.actions.justify-space-between
.tags
v-chip.ml-1.px-2(v-for='tag in event.tags' small
:key='tag' outlined color='primary' @click="$emit('tagclick', tag)") {{tag}}
//- title
h2 {{event.title}}
v-menu(offset-y)
template(v-slot:activator="{on}")
v-btn.align-self-end(icon v-on='on' color='primary')
v-icon mdi-dots-vertical
v-list(dense)
v-list-item-group
v-list-item(v-clipboard:success="() => $root.$message('common.copied', { color: 'success' })"
v-clipboard:copy='`${settings.baseurl}/event/${event.id}`')
v-list-item-icon
v-icon mdi-content-copy
v-list-item-content
v-list-item-title {{$t('common.copy_link')}}
v-list-item(:href='`/api/event/${event.id}.ics`')
v-list-item-icon
v-icon mdi-calendar-export
v-list-item-content
v-list-item-title {{$t('common.add_to_calendar')}}
//- date / place
.date
div <v-icon name='clock'/> {{event|when('home')}}
div <v-icon name='map-marker-alt' /> {{event.place.name}}
ul.tags(v-if='showTags && event.tags')
li(v-for='tag in event.tags' :key='tag') {{tag}}
li(v-if='settings.enable_federation && event.resources && event.resources.length') <u>{{$tc('common.n_resources', event.resources.length)}}</u>
</template>
<script>
import { mapState, mapActions } from 'vuex'
import { mapState } from 'vuex'
export default {
props: {
event: Object,
showTags: {
type: Boolean,
default: true
},
showImage: {
type: Boolean,
default: true
}
event: { type: Object, default: () => ({}) }
},
computed: {
...mapState(['settings']),
date () {
return new Date(this.event.start_datetime).getDate()
},
link () {
if (this.event.recurrent) {
return `${this.event.id}_${this.event.start_datetime}`
}
return this.event.id
}
}
computed: mapState(['settings'])
}
</script>
<style lang='less'>
@import '../assets/style.less';
@media only screen and (min-width: 574px) {
.event {
height: 100%;
}
}
.event {
padding: 3px;
display: flex;
flex-direction: column;
// height: 100%;
&:hover {
text-decoration: none;
}
img {
width: 100%;
max-height: 250px;
object-fit: cover;
object-position: top;
}
.event-info {
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
background-color: #111214;
}
.content-info {
padding: 0.8em 1em;
h2 {
color: @success;
font-size: 16px;
font-size: 1.2rem;
font-weight: 400;
margin: 0px;
}
p {
max-height: 92px;
overflow: hidden;
color: white;
margin: 0px;
}
.date {
font-weight: 400;
font-size: 1rem;
color: white;
}
}
.tags {
font-size: 15px;
padding: 1px;
margin-bottom: 0;
display:flex;
flex-wrap: wrap;
justify-content: center;
li {
background: #1B1F21;
display: inline-block;
padding: 2px 10px;
color: rgba(255,255,255,0.9);
margin: 1px;
text-align: center;
flex-grow: 1;
}
}
}
</style>
</script>

View file

@ -1,42 +1,39 @@
<template lang='pug'>
div
p(v-html="$t('event.follow_me_description', { title: settings.title, account: `@${settings.instance_name}@${domain}`})")
el-input(v-model='instance_hostname')
a(slot='append' :href='link' target='_blank')
el-button(:disabled='(!couldGo || !proceed)' plain type="primary" icon='el-icon-document') {{$t("common.follow")}}
p.mt-2 <img class='instance_thumb' :src="instance.thumbnail"/> {{instance.title}}
v-card
v-card-title(v-text="$t('common.follow_me_title')")
v-card-text
p(v-html="$t('event.follow_me_description', { title: settings.title, account: `@${settings.instance_name}@${domain}`})")
v-text-field(
:rules="[$validators.required('common.url')]"
:label="$t('common.url')"
v-model='instance_hostname')
p <img class='instance_thumb' :src="instance.thumbnail"/> {{instance.title}}
v-card-actions
v-spacer
v-btn(color='warning' @click="$emit('close')") {{$t("common.cancel")}}
v-btn(:disabled='(!couldGo || !proceed)'
:loading='loading' color="primary") {{$t("common.follow")}}
</template>
<script>
import { mapState } from 'vuex'
import { Message } from 'element-ui'
import debounce from 'lodash/debounce'
import url from 'url'
export default {
name: 'embedEvent',
name: 'FollowMe',
props:
{ isDialog: { type: Boolean, default: false } },
data () {
return {
instance_hostname: '',
proceed: false,
instance: {},
loading: false,
get_instance_info: debounce(this.getInstanceInfo, 500)
}
},
methods: {
getInstanceInfo () {
const instance_url = `https://${this.instance_hostname}/api/v1/instance`
fetch(instance_url)
.then( ret => ret.json())
.then(ret => {
this.instance = ret
this.proceed = true
})
.catch( e => {
this.proceed = false
})
}
},
computed: {
...mapState(['settings']),
domain () {
@ -45,7 +42,6 @@ export default {
},
couldGo () {
// check if is mastodon
const instance_url = `https://${this.instance_hostname}/api/v1/instance`
this.get_instance_info()
return true
},
@ -53,6 +49,22 @@ export default {
// check if exists
return `https://${this.instance_hostname}/authorize_interaction?uri=${this.settings.instance_name}@${this.domain}`
}
},
methods: {
getInstanceInfo () {
if (!this.instance_hostname) {
return
}
const instance_url = `https://${this.instance_hostname}/api/v1/instance`
this.$axios.$get(instance_url)
.then(ret => {
this.instance = ret
this.proceed = true
})
.catch(e => {
this.proceed = false
})
}
}
}
</script>
@ -60,4 +72,4 @@ export default {
.instance_thumb {
height: 20px;
}
</style>
</style>

33
components/Footer.vue Normal file
View file

@ -0,0 +1,33 @@
<template lang="pug">
v-footer(color='secondary')
v-btn(color='primary' text href='https://gancio.org') Gancio {{settings.version}}
v-btn(v-for='link in settings.footerLinks'
:key='link.label' color='primary' text :href='link.href') {{link.label}}
v-menu(v-if='settings.enable_trusted_instances && settings.trusted_instances && settings.trusted_instances.length'
offset-y bottom open-on-hover transition="slide-y-transition")
template(v-slot:activator="{ on, attrs }")
v-btn(v-bind='attrs' v-on='on' color='primary' text) {{$t('common.places')}}
v-list
v-list-item(v-for='instance in settings.trusted_instances'
:key='instance.name'
:href='instance.url'
two-line)
v-list-item-avatar
v-img(:src='`${instance.url}/favicon.ico`')
v-list-item-content
v-list-item-title {{instance.name}}
v-list-item-subtitle {{instance.label}}
//- v-btn(v-if='settings.enable_federation' text rel='me' @click.prevent='showFollowMe=true') follow me
//- v-btn(nuxt to='/about' text) about
//- v-btn(href='https://blog.gancio.org' text) blog
//- v-btn(href='https://framagit.org/les/gancio' text) source
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: mapState(['settings'])
}
</script>

View file

@ -1,61 +0,0 @@
<template lang="pug">
section
el-backtop(target='body')
//- el-backtop(target='#home')
client-only
Calendar
.row.m-0
.p-0.col-sm-6.col-lg-4.col-xl-3(v-for='event in events')
a(:id='event.newDay' v-if='event.newDay')
.d-block.d-sm-none
el-divider {{event.start_datetime|day}}
//- p(style='color: white;') {{event}}
Event(
:id='event.start_datetime'
:key='event.id'
:event='event'
)
</template>
<script>
import { mapGetters, mapState } from 'vuex'
import Event from '@/components/Event'
import Calendar from '@/components/Calendar'
export default {
name: 'Home',
head () {
return {
title: this.settings.title,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{ hid: 'description', name: 'description', content: this.settings.description },
{ hid: 'og-description', name: 'og:description', content: this.settings.description },
{ hid: 'og-title', property: 'og:title', content: this.settings.title },
{ hid: 'og-url', property: 'og:url', content: this.settings.baseurl },
{ property: 'og:image', content: this.settings.baseurl + '/favicon.ico' }
],
link: [
{ rel: 'alternate', type: 'application/rss+xml', title: this.settings.title, href: this.settings.baseurl + '/feed/rss' }
]
}
},
components: { Calendar, Event },
computed: {
events () {
return this.in_past ? this.filteredEventsWithPast : this.filteredEvents
},
...mapGetters(['filteredEvents', 'filteredEventsWithPast']),
...mapState(['settings', 'in_past'])
}
}
</script>
<style lang="less">
section {
width: 100%;
max-width: 1500px;
margin: 0 auto;
}
</style>

View file

@ -1,22 +1,20 @@
<template lang="pug">
<template lang='pug'>
div#list
el-divider(v-if='title') {{title}}
el-timeline
el-timeline-item(
v-for='event in events'
:key='`${event.id}_${event.start_datetime}`'
:timestamp='event|when'
placement='top' icon='el-icon-arrow-down' size='large'
)
div.float-right
small @{{event.place.name}}
a(:href='"/event/" + link(event)' target='_blank') {{event.title}}
hr
v-list(dense)
v-list-item
h3(v-if='title') {{title}}
v-list-item(
target='_blank'
:to='`/event/${event.id}`'
v-for='event in computedEvents'
:key='`${event.id}_${event.start_datetime}`' small)
v-list-item-content
v-list-item-subtitle <v-icon small color='success' v-if='event.parentId'>mdi-repeat</v-icon> {{event|when}}
span.primary--text.ml-1 @{{event.place.name}}
v-list-item-title(v-text='event.title')
//- a.text-body-1(:href='`/event/${event.id}`' target='_blank') {{event.title}}
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'List',
@ -52,15 +50,10 @@ export default {
default: true
}
},
data () {
return { }
},
methods: {
link (event) {
if (event.recurrent) {
return `${event.id}_${event.start_datetime}`
}
return event.id
computed: {
computedEvents () {
if (!this.maxEvents) { return this.events }
return this.events.slice(0, this.maxEvents)
}
}
}
@ -69,23 +62,8 @@ export default {
#list {
max-width: 500px;
margin: 0 auto;
.el-timeline {
padding-left: 5px;
hr {
margin-top: 4px;
margin-bottom: 4px;
}
}
.el-timeline-item {
padding-bottom: 1px;
}
.el-timeline-item__timestamp {
margin: 0px;
padding: 0px;
.v-list-item__title {
white-space: normal !important;
}
}
</style>

44
components/Loading.vue Normal file
View file

@ -0,0 +1,44 @@
<template lang='pug'>
.loading-page(:class='{ loading }')
v-progress-circular(:size="100" :width="10" style='color: orangered;' indeterminate)
</template>
<script>
export default {
data: () => ({
loading: false
}),
methods: {
start () {
this.loading = true
},
finish () {
this.loading = false
}
}
}
</script>
<style scoped>
.loading-page {
z-index: -10;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
color: white;
background: rgba(0, 0, 0, 0.6);
text-align: center;
padding-top: 200px;
font-size: 4rem;
font-family: sans-serif;
transition: opacity .1s;
opacity: 0;
}
.loading {
z-index: 10;
opacity: 1;
}
</style>

View file

@ -1,84 +0,0 @@
<template lang='pug'>
el-dialog(:visible='show' @close='close' :close-on-click-modal='false' @opened='() => $refs.email.focus()'
append-to-body :title="$t('common.login')")
p(v-html="$t('login.description')")
div(v-loading='loading')
el-input.mb-2(v-model='email' type='email' name='email' prefix-icon='el-icon-user'
:placeholder='$t("common.email")' autocomplete='email' ref='email')
el-input.mb-1(v-model='password' @keyup.enter.native="submit"
prefix-icon='el-icon-lock' name='password'
type='password' :placeholder='$t("common.password")')
a(href='#' @click='forgot') {{$t('login.forgot_password')}}
span(slot='footer')
el-button.mr-1(plain type="success"
:disabled='disabled' @click='submit') {{$t('common.login')}}
nuxt-link(to='/?ref=register' v-if='settings.allow_registration')
el-button.mt-1(plain type="primary") {{$t('login.not_registered')}}
</template>
<script>
import { mapActions, mapState } from 'vuex'
import { Message } from 'element-ui'
import get from 'lodash/get'
export default {
name: 'Login',
props: ['show'],
data () {
return {
password: '',
email: '',
loading: false
}
},
computed: {
...mapState(['settings']),
disabled () {
return !this.email || !this.password
}
},
methods: {
...mapActions(['login']),
close () {
this.$router.replace('/')
this.$emit('close')
},
async forgot () {
if (!this.email) {
Message({ message: this.$t('login.insert_email'), showClose: true, type: 'error' })
this.$refs.email.focus()
return
}
this.loading = true
await this.$axios.$post('/user/recover', { email: this.email })
this.loading = false
Message({ message: this.$t('login.check_email'), type: 'success' })
},
async submit (e) {
if (this.disabled) { return false }
e.preventDefault()
try {
this.loading = true
await this.$auth.loginWith('local', { data: { email: this.email, password: this.password } })
const user = await this.$axios.$get('/auth/user')
this.$auth.setUser(user)
this.loading = false
Message({ message: this.$t('login.ok'), showClose: true, type: 'success' })
this.close()
} catch (e) {
e = get(e, 'response.data.message', e)
Message({ message: this.$t('login.error') + this.$t(e), showClose: true, type: 'error' })
this.loading = false
return
}
this.email = this.password = ''
}
}
}
</script>

View file

@ -1,96 +1,113 @@
<template lang="pug">
el-menu.d-flex.nav(mode='horizontal' background-color="#222C32")
Login(:show='showLogin', @close='showLogin=false')
Register(:show='showRegister', @close='showRegister=false')
nuxt-link(to='/about')
el-menu-item(:title="$t('common.info')")
img#logo(src='/favicon.ico')
v-app-bar(app)
nuxt-link(v-if='!$auth.loggedIn' to='/?ref=login')
el-menu-item(:title="$t('common.login')")
v-icon(color='lightgreen' name='user')
//- logo, title and description
v-list-item(:to='$route.name==="index"?"/about":"/"')
v-list-item-avatar(tile)
v-img(src='/logo.png')
v-list-item-content.d-none.d-sm-flex
v-list-item-title
h2 {{settings.title}}
v-list-item-subtitle {{settings.description}}
nuxt-link(v-if='could_add' to='/add')
el-menu-item(:title="$t('common.add_event')")
v-icon(color='lightgreen' name='plus')
v-spacer
el-popover(placement="bottom" trigger="click")
Search(past-filter recurrent-filter)
el-menu-item(slot='reference' :title="$t('common.search')" icon='el-share-button')
v-icon(color='lightblue' name='search')
el-badge(v-if='filters.tags.length+filters.places.length>0' is-dot type='warning')
v-tooltip(bottom) {{$t('common.add_event')}}
template(v-slot:activator='{ on }')
v-btn(v-if='could_add' icon nuxt to='/add' v-on='on')
v-icon(large color='primary') mdi-plus
nuxt-link(v-if='$auth.loggedIn' to='/settings')
el-menu-item(:title="$t('common.settings')")
v-icon(color='orange' name='cog')
v-tooltip(bottom) {{$t('common.share')}}
template(v-slot:activator='{ on }')
v-btn(icon nuxt to='/export' v-on='on')
v-icon mdi-share-variant
nuxt-link(v-if='$auth.user && $auth.user.is_admin' to='/admin')
el-menu-item(:title="$t('common.admin')")
v-icon(color='lightblue' name='tools')
v-tooltip(v-if='!$auth.loggedIn' bottom) {{$t('common.login')}}
template(v-slot:activator='{ on }')
v-btn(icon nuxt to='/login' v-on='on')
v-icon mdi-login
nuxt-link(to='/export')
el-menu-item(:title="$t('common.share')")
v-icon(name='share' color='yellow')
v-menu(v-else
offset-y bottom open-on-hover transition="slide-y-transition")
template(v-slot:activator="{ on, attrs }")
v-btn(icon v-bind='attrs' v-on='on')
v-icon mdi-dots-vertical
v-list
v-list-item(nuxt to='/settings')
v-list-item-icon
v-icon mdi-cog
v-list-item-content
v-list-item-title {{$t('common.settings')}}
el-menu-item(v-if='$auth.loggedIn' @click='logout' :title="$t('common.logout')")
v-icon(color='red' name='sign-out-alt')
v-list-item(v-if='$auth.user.is_admin' nuxt to='/admin')
v-list-item-icon
v-icon mdi-account
v-list-item-content
v-list-item-title {{$t('common.admin')}}
el-menu-item(:title="$t('common.feed')" v-clipboard:copy='`${settings.baseurl}/feed/rss`' v-clipboard:success='copyLink')
v-icon(color='orange' name='rss')
v-list-item(@click='logout')
v-list-item-icon
v-icon mdi-logout
v-list-item-content
v-list-item-title {{$t('common.logout')}}
v-btn(icon v-clipboard:copy='feedLink' v-clipboard:success='copyLink')
v-icon(color='orange') mdi-rss
</template>
<script>
import { Message } from 'element-ui'
import { mapState } from 'vuex'
import Search from '@/components/Search'
import Login from '@/components/Login'
import Register from '@/components/Register'
export default {
name: 'Nav',
components: { Search, Login, Register },
data () {
return {
showLogin: this.$route.query.ref === 'login',
showRegister: this.$route.query.ref === 'register'
}
},
computed: {
...mapState(['filters', 'settings']),
feedLink () {
const tags = this.filters.tags && this.filters.tags.join(',')
const places = this.filters.places && this.filters.places.join(',')
let query = ''
if (tags || places) {
query = '?'
if (tags) {
query += 'tags=' + tags
if (places) { query += '&places=' + places }
} else {
query += 'places=' + places
}
}
return `${this.settings.baseurl}/feed/rss${query}`
},
could_add () {
return (this.$auth.loggedIn || this.settings.allow_anon_event)
},
...mapState(['filters', 'settings'])
},
watch: {
'$route.query.ref' (value) {
if (value === 'register') {
this.showRegister = true
this.showLogin = false
} else if (value === 'login') {
this.showLogin = true
this.showRegister = false
}
}
},
methods: {
copyLink () {
Message({ message: this.$t('common.feed_url_copied'), type: 'success', showClose: true })
this.$root.$message('common.feed_url_copied')
},
logout () {
Message({ showClose: true, message: this.$t('common.logout_ok'), type: 'success' })
this.$root.$message('common.logout_ok')
this.$auth.logout()
},
async createTrustedInstance () {
let url = this.instance_url
if (!url.match(/^https?:\/\//)) {
url = `https://${url}`
}
try {
const instance = await this.$axios.$get(`${url}/.well-known/nodeinfo/2.0`)
const trusted_instance = {
url,
name: instance.metadata.nodeName,
description: instance.metadata.nodeDescription,
place: instance.metadata.placeDescription
}
this.setSetting({ key: 'trusted_instances', value: this.settings.trusted_instances.concat(trusted_instance) })
} catch (e) {
this.$root.$message(e, { color: 'error' })
}
}
}
}
</script>
<style>
.el-menu.el-menu--horizontal {
border-bottom: none;
}
#logo {
height: 30px;
}
</style>

View file

@ -1,77 +0,0 @@
<template lang='pug'>
el-dialog(:visible='show' @close='close' :close-on-click-modal='false'
append-to-body :title="$t('common.register')")
p(v-html="$t('register.description')")
div(v-loading='loading')
el-input.mb-2(ref='email' v-model='user.email' type='email' required
:placeholder='$t("common.email")' autocomplete='email'
prefix-icon='el-icon-message' name='email')
el-input.mb-2(v-model='user.password' type="password"
placeholder="Password" name='password' required prefix-icon='el-icon-lock')
el-input.mb-2(v-model='user.description' type="textarea" rows='3' :placeholder="$t('common.description')")
span(slot='footer')
el-button(plain type="success" :disabled='disabled' @click='register') {{$t('common.send')}} <v-icon name='chevron-right'/>
</template>
<script>
import { mapActions, mapState } from 'vuex'
import { Message } from 'element-ui'
import get from 'lodash/get'
export default {
name: 'Register',
props: ['show'],
data () {
return {
loading: false,
user: {}
}
},
head () {
return {
title: this.settings.title + ' - ' + this.$t('common.register')
}
},
validate ({ store }) {
return store.state.settings.allow_registration
},
computed: {
...mapState(['settings']),
disabled () {
if (process.server) { return false }
return !this.user.password || !this.user.email || !this.user.description
}
},
methods: {
close () {
this.$router.replace('/')
this.$emit('close')
},
async register () {
this.loading = true
try {
const { user } = await this.$axios.$post('/user/register', this.user)
Message({
showClose: true,
message: this.$t(`register.${user.is_admin ? 'admin_' : ''}complete`),
type: 'success'
})
this.close()
} catch (e) {
const error = get(e, 'response.data.errors[0].message', String(e))
Message({
showClose: true,
message: this.$t(error),
type: 'error'
})
}
this.loading = false
}
}
}
</script>

View file

@ -1,75 +1,94 @@
<template lang="pug">
div.ml-2.mt-1.text-center
//- el-switch.mb-1(v-if='$auth.loggedIn'
//- active-text='solo miei'
//- inactive-text='tutti'
//- inactive-color='lightgreen'
//- v-model='onlyMine'
//- )
el-switch.mt-1.mb-1.ml-2.d-block(
v-container.pt-0.pt-md-2
v-switch.mt-0(
v-if='recurrentFilter && settings.allow_recurrent_event'
inactive-text=''
:active-text="$t('event.recurrent_event_too')"
inactive-color='lightgreen'
v-model='showRecurrent'
)
el-switch.mt-1.mb-1.ml-2.d-block(
v-if='pastFilter'
:inactive-text="$t('event.only_future')"
:active-text="$t('event.past_too')"
inactive-color='lightgreen'
v-model='showPast'
)
client-only
el-select.search(v-model='filter'
multiple
filterable collapse-tags default-first-option
:placeholder='$t("common.search")')
el-option(v-for='(keyword, id) in keywords' :key='keyword.value'
:label='keyword.label' :value='keyword.value')
v-model='filters.show_recurrent'
inset color='primary'
hide-details
:label="$t('event.show_recurrent')"
@change="toggleShowRecurrent")
v-autocomplete.mt-0(
:label='$t("common.search")'
:items='keywords'
hide-details
@change='change'
:value='selectedFilters'
clearable
:search-input.sync='search'
item-text='label'
return-object
chips single-line
multiple)
template(v-slot:selection="data")
v-chip(v-bind="data.attrs"
close
@click:close='remove(data.item)'
:input-value="data.selected")
v-avatar(left)
v-icon {{data.item.type === 'place' ? 'mdi-map-marker' : 'mdi-tag' }}
span {{ data.item.label }}
template(v-slot:item='{ item }')
v-list-item-avatar
v-icon {{item.type === 'place' ? 'mdi-map-marker' : 'mdi-tag' }}
v-list-item-content
v-list-item-title(v-text='item.label')
</template>
<script>
import { mapState, mapActions } from 'vuex'
import { mapState } from 'vuex'
export default {
name: 'Search',
props: {
pastFilter: Boolean,
recurrentFilter: Boolean
recurrentFilter: { type: Boolean, default: true },
filters: { type: Object, default: () => {} }
},
data () {
return {
onlyMine: false
tmpfilter: null,
search: ''
}
},
methods: mapActions(['setSearchPlaces', 'setSearchTags', 'showPastEvents', 'showRecurrentEvents']),
computed: {
...mapState(['tags', 'places', 'filters', 'settings']),
// TOFIX: optimize
...mapState(['tags', 'places', 'settings']),
selectedFilters () {
const tags = this.tags.filter(t => this.filters.tags.includes(t.tag)).map(t => ({ type: 'tag', label: t.tag, weigth: t.weigth, id: t.tag }))
const places = this.places.filter(p => this.filters.places.includes(p.id))
.map(p => ({ type: 'place', label: p.name, weigth: p.weigth, id: p.id }))
const keywords = tags.concat(places).sort((a, b) => b.weigth - a.weigth)
return keywords
},
keywords () {
const tags = this.tags.map(t => ({ value: 't' + t.tag, label: t.tag, weigth: t.weigth }))
const places = this.places.map(p => ({ value: 'p' + p.id, label: p.name, weigth: p.weigth }))
return tags.concat(places).sort((a, b) => b.weigth - a.weigth)
},
showPast: {
set (value) { this.showPastEvents(value) },
get () { return this.filters.show_past_events }
},
showRecurrent: {
set (value) { this.showRecurrentEvents(value) },
get () { return this.filters.show_recurrent_events }
},
filter: {
set (filters) {
const tags = filters.filter(f => f[0] === 't').map(t => t.slice(1))
this.setSearchTags(tags)
const places = filters.filter(f => f[0] === 'p').map(p => +p.slice(1))
this.setSearchPlaces(places)
},
get () {
return this.filters.tags.map(t => 't' + t).concat(this.filters.places.map(p => 'p' + p))
const tags = this.tags.map(t => ({ type: 'tag', label: t.tag, weigth: t.weigth, id: t.tag }))
const places = this.places.map(p => ({ type: 'place', label: p.name, weigth: p.weigth, id: p.id }))
const keywords = tags.concat(places).sort((a, b) => b.weigth - a.weigth)
return keywords
}
},
methods: {
remove (item) {
const filters = {
tags: item.type === 'tag' ? this.filters.tags.filter(f => f !== item.id) : this.filters.tags,
places: item.type === 'place' ? this.filters.places.filter(f => f !== item.id) : this.filters.places,
show_recurrent: this.filters.show_recurrent
}
this.$emit('update', filters)
},
toggleShowRecurrent (v) {
const filters = {
tags: this.filters.tags,
places: this.filters.places,
show_recurrent: v
}
this.$emit('update', filters)
},
change (filters) {
filters = {
tags: filters.filter(t => t.type === 'tag').map(t => t.id),
places: filters.filter(p => p.type === 'place').map(p => p.id),
show_recurrent: this.filters.show_recurrent
}
this.$emit('update', filters)
}
}
}

40
components/Snackbar.vue Normal file
View file

@ -0,0 +1,40 @@
<template lang='pug'>
v-snackbar(
v-model="active"
:color="color"
:bottom="bottom"
:top="top"
:left="left"
:right="right"
:timeout="timeout")
v-icon.mr-3(color="white") {{icon}}
span {{ message }}
template(v-slot:action="{ }")
v-icon(size="16" @click="active = false") mdi-close-circle
</template>
<script>
export default {
data () {
return {
icon: 'md-alert',
color: 'secondary',
bottom: true,
top: false,
left: false,
right: false,
active: false,
timeout: 5000,
message: ''
}
},
created () {
this.$root.$message = (message, opts = {}) => {
this.active = true
this.message = this.$t(message, opts)
this.color = opts.color || 'secondary'
this.icon = opts.icon || 'md-alert'
}
}
}
</script>

View file

@ -0,0 +1,111 @@
<template lang='pug'>
v-container
v-card-title {{$t('common.announcements')}}
v-card-subtitle(v-html="$t('admin.announcement_description')")
v-dialog(v-model='dialog' width='800px')
v-card
v-card-title {{$t('admin.new_announcement')}}
v-card-text
v-form(v-model='valid' ref='announcement' @submit.prevent='save')
v-text-field(v-model='announcement.title' :label='$t("common.title")')
Editor.mt-2(v-model='announcement.announcement'
border no-save max-height='400px' :placeholder="$t('common.description')")
v-card-actions
v-spacer
v-btn(@click='dialog=false' color='error') {{$t('common.cancel')}}
v-btn(@click='save' color='primary' :disabled='loading' :loading='loading') {{$t(`common.${editing?'save':'send'}`)}}
v-btn(@click='openDialog' text color='primary') <v-icon>mdi-plus</v-icon> {{$t('common.add')}}
v-card-text
v-data-table(
v-if='announcements.length'
:hide-default-footer='announcements.length<10'
:headers='headers'
:items='announcements')
template(v-slot:item.actions='{ item }')
v-btn(text small @click.stop='toggle(item)'
:color='item.visible?"warning":"success"') {{item.visible?$t('common.disable'):$t('common.enable')}}
v-btn(text small @click='edit(item)' color='primary') {{$t('common.edit')}}
v-btn(text small @click='remove(item)' color='error') {{$t('common.delete')}}
</template>
<script>
import { mapActions } from 'vuex'
import cloneDeep from 'lodash/cloneDeep'
import Editor from '../Editor'
import Announcement from '../Announcement'
export default {
components: { Editor, Announcement },
data () {
return {
valid: false,
dialog: false,
editing: false,
announcements: [],
loading: false,
headers: [
{ value: 'title', text: 'Title' },
{ value: 'actions', text: 'Actions', align: 'right' }
],
announcement: { title: '', announcement: '' }
}
},
async mounted () {
this.announcements = await this.$axios.$get('/announcements')
},
methods: {
...mapActions(['setAnnouncements']),
edit (announcement) {
this.announcement.title = announcement.title
this.announcement.announcement = announcement.announcement
this.announcement.id = announcement.id
this.editing = true
this.dialog = true
},
openDialog () {
this.announcement = { title: '', announcement: '' }
this.dialog = true
this.$nextTick(() => this.$refs.announcement.reset())
},
async toggle (announcement) {
try {
announcement.visible = !announcement.visible
await this.$axios.$put(`/announcements/${announcement.id}`, announcement)
this.announcements = this.announcements.map(a => a.id === announcement.id ? announcement : a)
this.setAnnouncements(cloneDeep(this.announcements.filter(a => a.visible)))
} catch (e) {}
},
async remove (announcement) {
const ret = await this.$root.$confirm('admin.delete_announcement_confirm')
if (!ret) { return }
this.$axios.delete(`/announcements/${announcement.id}`)
.then(() => {
this.$root.$message('admin.announcement_remove_ok')
this.announcements = this.announcements.filter(a => a.id !== announcement.id)
})
},
async save () {
this.loading = true
try {
let announcement = null
if (this.editing) {
announcement = await this.$axios.$put(`/announcements/${this.announcement.id}`, this.announcement)
this.announcements = this.announcements.map(a => a.id === announcement.id ? announcement : a)
} else {
announcement = await this.$axios.$post('/announcements', this.announcement)
this.announcements = this.announcements.concat(announcement)
}
this.setAnnouncements(cloneDeep(this.announcements))
this.announcement = { title: '', announcement: '' }
this.$refs.announcement.reset()
this.editing = false
this.dialog = false
} catch (e) {
console.error(e)
}
this.loading = false
}
}
}
</script>

View file

@ -0,0 +1,54 @@
<template lang='pug'>
v-container
v-card-title {{$t('common.events')}}
v-card-subtitle {{$t('admin.event_confirm_description')}}
v-card-text
v-data-table(
:hide-default-footer='unconfirmedEvents.length<10'
:items='unconfirmedEvents'
:headers='headers')
template(v-slot:item.actions='{ item }')
v-btn(text small @click='confirm(item)' color='success') {{$t('common.confirm')}}
v-btn(text small :to='`/event/${item.id}`' color='success') {{$t('common.preview')}}
v-btn(text small :to='`/add/${item.id}`' color='warning') {{$t('common.edit')}}
v-btn(text small @click='remove(item)'
color='error') {{$t('common.delete')}}
</template>
<script>
export default {
props: {
unconfirmedEvents: { type: Array, default: () => [] }
},
data () {
return {
valid: false,
dialog: false,
editing: false,
headers: [
{ value: 'title', text: 'Title' },
{ value: 'actions', text: 'Actions', align: 'right' }
]
}
},
methods: {
edit (event) {
this.$router.push(`/add/${event.id}`)
},
async confirm (event) {
try {
await this.$axios.$put(`/event/confirm/${event.id}`)
this.$emit('confirmed', event.id)
this.$root.$message('event.confirmed')
} catch (e) {}
},
async remove (event) {
const ret = await this.$root.$confirm('event.remove_confirmation')
if (!ret) { return }
await this.$axios.delete(`/event/${event.id}`)
this.$root.$message('admin.event_remove_ok')
}
}
}
</script>

View file

@ -1,165 +1,95 @@
<template lang="pug">
div
el-form(label-width='200px')
el-form-item(:label="$t('admin.enable_federation')")
el-popover(:content="$t('admin.enable_federation_help')" placement='right' trigger='hover')
span(slot='reference')
el-switch(v-model='enable_federation')
v-container
v-card-title {{$t('common.federation')}}
v-card-text
v-switch(v-model='enable_federation'
:label="$t('admin.enable_federation')"
persistent-hint
inset
:hint="$t('admin.enable_federation_help')")
el-form-item(v-show='enable_federation' :label="$t('admin.enable_resources')")
el-popover(:content="$t('admin.enable_resources_help')" placement='right' trigger='hover')
span(slot='reference')
el-switch(v-model='enable_resources')
template(v-if='enable_federation')
el-form-item(v-show='enable_federation' :label="$t('admin.hide_boost_bookmark')")
el-popover(:content="$t('admin.hide_boost_bookmark_help')" placement='right' trigger='hover')
span(slot='reference')
el-switch(v-model='hide_boosts')
v-switch.mt-4(v-model='enable_resources'
:label="$t('admin.enable_resources')"
:hint="$t('admin.enable_resources_help')"
persistent-hint inset)
el-form-item(v-show='enable_federation' :label="$t('admin.instance_name')")
el-popover(:content="$t('admin.instance_name_help')" placement='right' trigger='hover')
span(slot='reference')
el-input.w-25(v-model='instance_name' placeholder='Instance name')
p Follow this instance from <u>@{{instance_name}}@{{settings.baseurl|url2host}}</u>
el-row(v-if='enable_federation')
el-col(:span='12')
el-divider {{$t('common.instances')}}
el-input(v-model='instancesFilter' :placeholder="$t('admin.filter_instances')")
el-table(:data='paginatedInstances' small @row-click='instanceSelected')
el-table-column(label='Domain' width='180')
template(slot-scope='data')
span(slot='reference') {{data.row.domain}}
el-table-column(label='Name' width='100')
template(slot-scope='data')
span(slot='reference') {{data.row.name}}
el-table-column(label='Users' width='60')
template(slot-scope='data')
span(slot='reference') {{data.row.users}}
el-table-column(:label="$t('common.actions')" width='120')
template(slot-scope='data')
el-button-group
el-button(size='mini'
:type='data.row.blocked?"danger":"warning"'
@click='toggleBlock(data.row)') {{data.row.blocked?$t('admin.unblock'):$t('admin.block')}}
client-only
el-pagination(v-if='enable_federation && instances.length>perPage' :page-size='perPage' :currentPage.sync='instancePage' :total='instances.length')
v-switch.mt-4(v-model='hide_boosts'
:label="$t('admin.hide_boost_bookmark')"
:hint="$t('admin.hide_boost_bookmark_help')"
persistent-hint inset)
el-col.float-right(:span='11' align='right')
el-divider {{$t('common.users')}}
el-input(v-model='usersFilter' :placeholder="$t('admin.filter_users')")
client-only
el-pagination(v-if='enable_federation && users.length>perPage' :page-size='perPage' :currentPage.sync='instancePage' :total='users.length')
el-table(:data='paginatedSelectedUsers' small)
el-table-column(label='User' width='150')
template(slot-scope='data')
span(slot='reference')
a(:href='data.row.object.id' target='_blank') {{data.row.object.name}}
small ({{data.row.object.preferredUsername}})
el-table-column(:label="$t('common.resources')" width='90')
template(slot-scope='data')
span {{data.row.resources.length}}
el-table-column(:label="$t('common.actions')" width='200')
template(slot-scope='data')
el-button-group
el-button(size='mini'
:type='data.row.blocked?"danger":"warning"'
@click='toggleUserBlock(data.row)') {{data.row.blocked?$t('admin.unblock'):$t('admin.block')}}
//- div.mt-4 {{$t('admin.instance_name')}}
v-text-field.mt-5(v-model='instance_name'
:label="$t('admin.instance_name')"
:hint="`${$t('admin.instance_name_help')} ${instance_ap_url}`"
placeholder='Instance name' persistent-hint
@blur='save("instance_name", instance_name)')
//- div(v-show='enable_federation')
el-divider {{$t('common.resources')}}
el-table(:data='paginatedResources' small :row-style='resourceStyle')
el-table-column(:label="$t('common.event')")
template(slot-scope='data')
span {{data.row.event}}
el-table-column(:label="$t('common.resources')")
template(slot-scope='data')
span(:class='{disabled: data.row.hidden}' v-html='data.row.data.content')
el-table-column(:label="$t('common.actions')" width="150")
template(slot-scope='data')
el-dropdown
el-button(type="primary" icon="el-icon-arrow-down" size='mini') {{$t('common.moderation')}}
el-dropdown-menu(slot='dropdown')
el-dropdown-item(v-if='!data.row.hidden' icon='el-icon-remove' @click.native='toggleHideResource(data.row)') {{$t('admin.hide_resource')}}
el-dropdown-item(v-else icon='el-icon-success' @click.native='toggleHideResource(data.row)') {{$t('admin.show_resource')}}
el-dropdown-item(icon='el-icon-delete' @click.native='deleteResource(data.row)') {{$t('admin.delete_resource')}}
el-dropdown-item(icon='el-icon-lock' @click.native='blockUser(data.row)') {{$t('admin.block_user')}}
v-switch.mt-4(v-model='enable_trusted_instances'
:label="$t('admin.enable_trusted_instances')"
persistent-hint inset
:hint="$t('admin.trusted_instances_help')")
template(v-if='enable_trusted_instances')
v-text-field.mt-4(v-model='instance_place'
:label="$t('admin.instance_place')"
persistent-hint
:hint="$t('admin.instance_place_help')"
@blur='save("instance_place", instance_place)'
)
v-dialog(v-model='dialogAddInstance' width="500px")
v-card
v-card-title {{$t('admin.add_trusted_instance')}}
v-card-text
v-form(v-model='valid' ref='form' lazy-validation)
v-text-field.mt-4(v-model='instance_url'
persistent-hint
:rules="[$validators.required('common.url')]"
:hint="$t('admin.add_trusted_instance')"
:label="$t('common.url')")
v-card-actions
v-spacer
v-btn(color='error' @click='dialogAddInstance=false') {{$t('common.cancel')}}
v-btn(color='primary' :disabled='!valid' @click='createTrustedInstance') {{$t('common.ok')}}
v-btn.mt-4(@click='dialogAddInstance = true' color='primary' text) <v-icon>mdi-plus</v-icon> Add instance
v-data-table(
v-if='settings.trusted_instances.length'
:hide-default-footer='settings.trusted_instances.length<10'
:headers='headers'
:items='settings.trusted_instances')
template(v-slot:item.actions="{item}")
v-btn(icon @click='deleteInstance(item)' color='error')
v-icon mdi-delete-forever
</template>
<script>
import { mapState, mapActions, mapGetters } from 'vuex'
import { mapActions, mapState } from 'vuex'
import axios from 'axios'
export default {
name: 'Federation',
data () {
data ({ $store, $options }) {
return {
perPage: 10,
instancePage: 1,
userPage: 1,
resourcePage: 1,
usersFilter: '',
instancesFilter: '',
users: [],
resources: [],
instances: [],
}
},
async mounted () {
console.error('mounted ')
this.instances = await this.$axios.$get('/instances')
this.resources = await this.$axios.$get('/resources')
// this.users = await this.$axios.$get('/users')
},
methods: {
...mapActions(['setSetting']),
// resourceStyle ({ row }) {
// if (row.hidden) return 'opacity: 0.5'
// },
async instanceSelected (instance) {
this.users = await this.$axios.$get(`/instances/${instance.domain}`)
},
async toggleBlock (instance) {
await this.$axios.post('/instances/toggle_block', { instance: instance.domain, blocked: !instance.blocked })
instance.blocked = !instance.blocked
},
async toggleUserBlock (user) {
await this.$axios.post('/instances/toggle_user_block', { user_id: user.ap_id })
user.blocked = !user.blocked
},
async toggleHideResource (resource) {
await this.$axios.put(`/resources/${resource.id}`, { hidden: !resource.hidden})
resource.hidden = !resource.hidden
instance_url: '',
instance_name: $store.state.settings.instance_name,
instance_place: $store.state.settings.instance_place,
url2host: $options.filters.url2host,
dialogAddInstance: false,
valid: false,
headers: [
{ value: 'name', text: 'Name' },
{ value: 'url', text: 'URL' },
{ value: 'label', text: 'Place' },
{ value: 'actions', text: 'Actions', align: 'right' }
]
}
},
computed: {
...mapState(['settings']),
paginatedResources () {
return this.resources.slice((this.resourcePage -1) * this.perPage,
this.resourcePage * this.perPage)
},
paginatedInstances () {
return this.filteredInstances.slice((this.instancePage - 1) * this.perPage,
this.instancePage * this.perPage)
},
filteredUsers () {
if (!this.usersFilter) return this.users
this.usersFilter = this.usersFilter.toLowerCase()
console.error(this.users)
return this.users.filter(user => user.name.includes(this.usersFilter) || user.preferredName.includes(this.usersFilter))
},
filteredInstances () {
if (!this.instancesFilter) return this.instances
this.instancesFilter = this.instancesFilter.toLowerCase()
return this.instances.filter(instance => instance.name.includes(this.instancesFilter) || instance.domain.includes(this.instancesFilter))
},
paginatedSelectedUsers () {
return this.filteredUsers.slice((this.userPage - 1) * this.perPage,
this.userPage * this.perPage)
},
instance_name: {
get () { return this.settings.instance_name },
set (value) { this.setSetting({ key: 'instance_name', value })}
},
enable_federation: {
get () { return this.settings.enable_federation },
set (value) { this.setSetting({ key: 'enable_federation', value }) }
@ -171,12 +101,52 @@ export default {
hide_boosts: {
get () { return this.settings.hide_boosts },
set (value) { this.setSetting({ key: 'hide_boosts', value }) }
},
enable_trusted_instances: {
get () { return this.settings.enable_trusted_instances },
set (value) { this.setSetting({ key: 'enable_trusted_instances', value }) }
},
instance_ap_url () {
const instance_url = this.settings.baseurl.match(/^https?:\/\/(.[^/:]+)/i)[1]
return `(@${this.instance_name}@${instance_url})`
}
},
methods: {
...mapActions(['setSetting']),
async createTrustedInstance () {
if (!this.$refs.form.validate()) { return }
try {
if (!this.instance_url.startsWith('http')) {
this.instance_url = `https://${this.instance_url}`
}
const instance = await axios.get(`${this.instance_url}/.well-known/nodeinfo/2.1`)
this.setSetting({
key: 'trusted_instances',
value: this.settings.trusted_instances.concat({
url: this.instance_url,
name: instance.data.metadata.nodeName,
label: instance.data.metadata.nodeLabel
})
})
this.$refs.form.reset()
this.dialogAddInstance = false
} catch (e) {
this.$root.$message(e, { color: 'error' })
}
},
async deleteInstance (instance) {
const ret = await this.$root.$confirm('admin.delete_trusted_instance_confirm')
if (!ret) { return }
this.setSetting({
key: 'trusted_instances',
value: this.settings.trusted_instances.filter(i => i.url !== instance.url)
})
},
save (key, value) {
if (this.settings[key] !== value) {
this.setSetting({ key, value })
}
}
}
}
</script>
<style lang="less">
.instance_thumb {
height: 20px;
}
</style>

View file

@ -0,0 +1,168 @@
<template lang='pug'>
v-container
v-card-title {{$t('common.moderation')}}
v-card-text
v-row
v-col(:span='12')
span {{$t('common.instances')}}
//- v-text-field(v-model='instancesFilter' :placeholder="$t('admin.filter_instances')")
v-data-table(:items='instances'
:items-per-page='5'
:hide-default-footer='instances.length<5'
dense :headers='instancesHeader'
@click:row='instanceSelected')
//- el-table-column(label='Domain' width='180')
//- template(slot-scope='data')
//- span(slot='reference') {{data.row.domain}}
//- el-table-column(label='Name' width='100')
//- template(slot-scope='data')
//- span(slot='reference') {{data.row.name}}
//- el-table-column(:label="$t('common.users')" width='70')
//- template(slot-scope='data')
//- span(slot='reference') {{data.row.users}}
//- el-table-column(:label="$t('common.actions')" width='120')
//- template(slot-scope='data')
//- el-button-group
//- el-button(size='mini'
//- :type='data.row.blocked?"danger":"warning"'
//- @click='toggleBlock(data.row)') {{data.row.blocked?$t('admin.unblock'):$t('admin.block')}}
v-col(:span='11')
span {{$t('common.users')}}
//- v-text-field(v-model='usersFilter' :placeholder="$t('admin.filter_users')")
v-data-table(:items='users'
:items-per-page='5'
:hide-default-footer='users.length<5'
dense :headers='usersHeader')
template(v-slot:item.username="{item}")
a(:href='item.ap_id') {{item.object.preferredUsername}}
//- el-table-column(:label="$t('common.user')" width='150')
//- template(slot-scope='data')
//- span(slot='reference')
//- a(:href='data.row.object.id' target='_blank') {{data.row.object.name}}
//- small ({{data.row.object.preferredUsername}})
//- el-table-column(:label="$t('common.resources')" width='90')
//- template(slot-scope='data')
//- span {{data.row.resources.length}}
//- el-table-column(:label="$t('common.actions')" width='200')
//- template(slot-scope='data')
//- el-button-group
//- el-button(size='mini'
//- :type='data.row.blocked?"danger":"warning"'
//- @click='toggleUserBlock(data.row)') {{data.row.blocked?$t('admin.unblock'):$t('admin.block')}}
div
v-card-title {{$t('common.resources')}}
v-data-table(:items='resources'
:hide-default-footer='resources.length<10'
)
//- el-table-column(:label="$t('common.event')")
//- template(slot-scope='data')
//- span {{data.row.event}}
//- el-table-column(:label="$t('common.resources')")
//- template(slot-scope='data')
//- span(:class='{disabled: data.row.hidden}' v-html='data.row.data.content')
//- el-table-column(:label="$t('common.user')" width='200')
//- template(slot-scope='data')
//- span(:class='{disabled: data.row.hidden}' v-html='data.row.data.actor')
//- el-table-column(:label="$t('common.actions')" width="150")
//- template(slot-scope='data')
//- el-dropdown
//- el-button(type="primary" icon="el-icon-arrow-down" size='mini') {{$t('common.moderation')}}
//- el-dropdown-menu(slot='dropdown')
//- el-dropdown-item(v-if='!data.row.hidden' icon='el-icon-remove' @click.native='hideResource(data.row, true)') {{$t('admin.hide_resource')}}
//- el-dropdown-item(v-else icon='el-icon-success' @click.native='hideResource(data.row, false)') {{$t('admin.show_resource')}}
//- el-dropdown-item(icon='el-icon-delete' @click.native='deleteResource(data.row)') {{$t('admin.delete_resource')}}
//- el-dropdown-item(icon='el-icon-lock' @click.native='toggleUserBlock(data.row.ap_user)') {{$t('admin.block_user')}}
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
name: 'Moderation',
data () {
return {
instances: [],
resources: [],
users: [],
usersHeader: [
{ value: 'username', text: 'Name' }
],
instancesHeader: [
{ value: 'domain', text: 'Domain' },
{ value: 'name', text: 'Name' },
{ value: 'users', text: 'N' }
],
resourcesHeader: [
{ value: '', text: '' }
]
}
},
computed: {
...mapState(['settings'])
// paginatedResources () {
// return this.resources.slice((this.resourcePage - 1) * this.perPage,
// this.resourcePage * this.perPage)
// },
// paginatedInstances () {
// return this.filteredInstances.slice((this.instancePage - 1) * this.perPage,
// this.instancePage * this.perPage)
// },
// filteredUsers () {
// if (!this.usersFilter) { return this.users }
// const usersFilter = this.usersFilter.toLowerCase()
// return this.users.filter(user => user.name.includes(usersFilter) || user.preferredName.includes(usersFilter))
// },
// filteredInstances () {
// if (!this.instancesFilter) { return this.instances }
// const instancesFilter = this.instancesFilter.toLowerCase()
// return this.instances.filter(instance =>
// (instance.name && instance.name.includes(instancesFilter)) ||
// (instance.domain && instance.domain.includes(instancesFilter))
// )
// },
// paginatedSelectedUsers () {
// return this.filteredUsers.slice((this.userPage - 1) * this.perPage,
// this.userPage * this.perPage)
// }
},
async mounted () {
this.instances = await this.$axios.$get('/instances')
this.resources = await this.$axios.$get('/resources')
// this.users = await this.$axios.$get('/users')
},
methods: {
...mapActions(['setSetting']),
resourceStyle ({ row }) {
if (row.hidden) {
return { opacity: 0.5 }
}
},
async instanceSelected (instance) {
this.users = await this.$axios.$get(`/instances/${instance.domain}`)
},
async hideResource (resource, hidden) {
await this.$axios.$put(`/resources/${resource.id}`, { hidden })
resource.hidden = hidden
},
async toggleUserBlock (ap_user) {
if (!ap_user.blocked) {
const ret = await this.$root.$confirm('admin.user_block_confirm')
if (!ret) { return }
}
await this.$axios.post('/instances/toggle_user_block', { ap_id: ap_user.ap_id })
ap_user.blocked = !ap_user.blocked
},
async deleteResource (resource) {
const ret = await this.$root.$confirm('admin.delete_resource_confirm')
if (!ret) { return }
await this.$axios.delete(`/resources/${resource.id}`)
this.resources = this.resources.filter(r => r.id !== resource.id)
},
async toggleBlock (instance) {
await this.$axios.post('/instances/toggle_block', { instance: instance.domain, blocked: !instance.blocked })
instance.blocked = !instance.blocked
}
}
}
</script>

View file

@ -1,57 +1,71 @@
<template lang='pug'>
div
p(v-html="$t('admin.place_description')")
el-form.mb-2(inline label-width='120px')
el-form-item(:label="$t('common.name')")
el-input.mr-1(:placeholder='$t("common.name")' v-model='place.name')
el-form-item(:label="$t('common.address')")
el-input.mr-1(:placeholder='$t("common.address")' v-model='place.address')
el-button(variant='primary' @click='savePlace') {{$t('common.save')}}
v-container
v-card-title {{$t('common.places')}}
v-card-subtitle(v-html="$t('admin.place_description')")
el-table(:data='paginatedPlaces' small)
el-table-column(:label="$t('common.name')" width='200')
template(slot-scope='data') {{data.row.name}}
el-table-column(:label="$t('common.address')" width='400')
template(slot-scope='data') {{data.row.address}}
el-table-column(:label="$t('common.actions')" width='200')
template(slot-scope='data')
el-button(size='mini'
type='success'
@click='place = data.row') {{$t('common.edit')}}
v-dialog(v-model='dialog' width='600')
v-card(color='secondary')
v-card-title {{$t('admin.edit_place')}}
v-card-text
v-form(v-model='valid' ref='form' lazy-validation)
v-text-field(
:rules="[$validators.required('common.name')]"
:label="$t('common.name')"
v-model='place.name'
:placeholder='$t("common.name")')
client-only
el-pagination(:page-size='perPage' :currentPage.sync='placePage' :total='places.length')
v-text-field(
:rules="[$validators.required('common.address')]"
:label="$t('common.address')"
v-model='place.address'
:placeholder='$t("common.address")')
v-card-actions
v-spacer
v-btn(@click='dialog=false' color='warning') {{$t('common.cancel')}}
v-btn(@click='savePlace' color='primary' :loading='loading'
:disable='!valid || loading') {{$t('common.save')}}
v-card-text
v-data-table(
:headers='headers'
:items='places')
template(v-slot:item.actions='{item}')
v-btn(@click='editPlace(item)' color='primary' icon)
v-icon mdi-pencil
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
data () {
return {
perPage: 10,
placePage: 0,
place: { name: '', address: '', id: null }
}
},
computed: {
...mapState(['places']),
paginatedPlaces () {
return this.places.slice((this.placePage - 1) * this.perPage,
this.placePage * this.perPage)
loading: false,
dialog: false,
valid: false,
place: { name: '', address: '', id: null },
headers: [
{ value: 'name', text: 'Name' },
{ value: 'address', text: 'Address' },
{ value: 'actions', text: 'Actions', align: 'right' }
]
}
},
computed: mapState(['places']),
methods: {
placeSelected (items) {
if (items.length === 0) {
this.place.name = this.place.address = ''
return
}
const item = items[0]
...mapActions(['updateMeta']),
editPlace (item) {
this.place.name = item.name
this.place.address = item.address
this.place.id = item.id
this.dialog = true
},
async savePlace () {
const place = await this.$axios.$put('/place', this.place)
if (!this.$refs.form.validate()) return
this.loading = true
await this.$axios.$put('/place', this.place)
this.updateMeta()
this.loading = false
this.dialog = false
}
}
}

View file

@ -1,44 +1,82 @@
<template lang="pug">
div
el-form(inline label-width="400px")
v-container
v-card-title {{$t('common.settings')}}
v-card-text
//- select timezone
client-only
el-form-item(:label="$t('admin.select_instance_timezone')")
el-select(v-model='instance_timezone' filterable)
el-option(v-for='timezone in timezones' :key='timezone.value' :value='timezone.value')
span.float-left {{timezone.value}}
small.float-right.text-danger {{timezone.offset}}
v-autocomplete(v-model='instance_timezone'
:label="$t('admin.select_instance_timezone')"
:hint="$t('admin.instance_timezone_description')"
:items="filteredTimezones"
persistent-hint
item-text='value'
item-value='value'
placeholder='Timezone, type to search')
template(v-slot:item='{ item }')
v-list-item-content
v-list-item-title {{item.value}}
v-list-item-subtitle {{item.offset}}
//- allow open registration
el-form-item(:label="$t('admin.allow_registration_description')")
el-switch(name='reg' v-model='allow_registration')
v-select.mt-5(
v-model='instance_locale'
:label="$t('admin.instance_locale')"
:hint="$t('admin.instance_locale_description')"
persistent-hint
:items='locales'
)
//- allow anon event
el-form-item(:label="$t('admin.allow_anon_event')")
el-switch(v-model='allow_anon_event')
v-text-field.mt-5(v-model='title'
:label="$t('common.title')"
:hint="$t('admin.title_description')"
@blur='save("title", title)'
persistent-hint
)
el-form-item(:label="$t('admin.allow_recurrent_event')")
el-switch(v-model='allow_recurrent_event')
v-text-field.mt-5(v-model='description'
:label="$t('common.description')"
:hint="$t('admin.description_description')"
persistent-hint
@blur='save("description", description)')
el-form-item(v-show='allow_recurrent_event' :label="$t('admin.recurrent_event_visible')")
el-switch(v-model='recurrent_event_visible')
v-switch.mt-5(v-model='allow_registration'
inset
:label="$t('admin.allow_registration_description')")
v-switch.mt-4(v-model='allow_anon_event'
inset
:label="$t('admin.allow_anon_event')")
v-switch.mt-4(v-model='allow_recurrent_event'
inset
:label="$t('admin.allow_recurrent_event')")
v-switch.mt-4(v-if='allow_recurrent_event'
v-model='recurrent_event_visible'
inset
:label="$t('admin.recurrent_event_visible')")
</template>
<script>
import { mapActions, mapState } from 'vuex'
import moment from 'moment-timezone'
import timezones from './timezones'
import _ from 'lodash'
import locales from '../../locales/esm'
export default {
name: 'Settings',
data ({ $store }) {
return {
title: $store.state.settings.title,
description: $store.state.settings.description,
locales: Object.keys(locales).map(locale => ({ value: locale, text: locales[locale] }))
}
},
computed: {
timezones () {
const current_timezone = moment.tz.guess()
return timezones
.filter(tz => tz !== current_timezone)
.concat([current_timezone])
.map(tz => ({ value: tz, offset: moment().tz(tz).format('z Z') }))
},
...mapState(['settings']),
instance_locale: {
get () { return this.settings.instance_locale },
set (value) { this.setSetting({ key: 'instance_locale', value }) }
},
instance_timezone: {
get () { return this.settings.instance_timezone },
set (value) { this.setSetting({ key: 'instance_timezone', value }) }
@ -58,8 +96,23 @@ export default {
recurrent_event_visible: {
get () { return this.settings.recurrent_event_visible },
set (value) { this.setSetting({ key: 'recurrent_event_visible', value }) }
},
filteredTimezones () {
const current_timezone = moment.tz.guess()
const ret = _(moment.tz.names())
.unshift(current_timezone)
.map(tz => ({ value: tz, offset: moment().tz(tz).format('z Z') }))
.value()
return ret
}
},
methods: mapActions(['setSetting'])
methods: {
...mapActions(['setSetting']),
save (key, value) {
if (this.settings[key] !== value) {
this.setSetting({ key, value })
}
}
}
}
</script>

174
components/admin/Theme.vue Normal file
View file

@ -0,0 +1,174 @@
<template lang="pug">
v-container
v-card-title {{$t('common.theme')}}
v-card-text
//- LOGO
v-file-input.mt-5(ref='upload'
:label="$t('admin.favicon')"
@change='uploadLogo'
accept='image/*')
template(slot='append-outer')
v-btn(color='warning' text @click='resetLogo') <v-icon>mdi-restore</v-icon> {{$t('common.reset')}}
v-img(:src='`${settings.baseurl}/favicon.ico?${logoKey}`'
max-width="100px" max-height="80px" contain)
v-switch.mt-5(v-model='is_dark'
inset
:label="$t('admin.is_dark')")
//- TODO choose theme colors
//- v-row
//- v-col(v-for='(color, i) in colors' :key='i')
//- v-menu(v-model='menu[i]'
//- :close-on-content-click="false"
//- transition="slide-x-transition"
//- offset-y
//- absolute
//- bottom
//- max-width="290px"
//- min-width="290px")
//- template(v-slot:activator='{ on }')
//- v-btn(:color='i' small
//- v-on='on') {{i}}
//- v-color-picker(light @update:color='c => updateColor(i, c)')
v-dialog(v-model='linkModal' width='500')
v-card
v-card-title {{$t('admin.add_footer_link')}}
v-card-text
v-form(v-model='valid' ref='linkModalForm')
v-text-field(v-model='link.label'
:rules="[$validators.required('common.label')]"
label='Label')
v-text-field(v-model='link.href'
:rules="[$validators.required('common.url')]"
:label="$t('common.url')")
v-card-actions
v-spacer
v-btn(link @click='linkModal=false' color='error') {{$t('common.cancel')}}
v-btn(link @click='addFooterLink' color='primary' :disabled='!valid') {{$t('common.add')}}
v-card-title {{$t('admin.footer_links')}}
v-card-text
v-btn(color='primary' text @click='openLinkModal') <v-icon>mdi-plus</v-icon> {{$t('admin.add_link')}}
v-btn(color='warning' text @click='reset') <v-icon>mdi-restore</v-icon> {{$t('common.reset')}}
v-list
v-list-item(v-for='link in settings.footerLinks'
:key='`${link.label}`')
v-list-item-content
v-list-item-title {{link.label}}
v-list-item-subtitle {{link.href}}
v-list-item-action
v-btn.float-right(icon color='accent' @click='editFooterLink(link)')
v-icon mdi-pencil
v-btn(icon color='error' @click='removeFooterLink(link)')
v-icon mdi-delete-forever
</template>
<script>
import { mapActions, mapState } from 'vuex'
export default {
name: 'Theme',
data () {
return {
valid: false,
logoKey: 0,
link: { href: '', label: '' },
linkModal: false,
menu: [false, false, false, false],
colors: { primary: '', secondary: '', accent: '', error: '', info: '', success: '', warning: '' }
// primary: {},
// secondary: {}
// }
}
},
computed: {
...mapState(['settings']),
// 'colors.primary': this.color('primary'),
// 'colors.secondary': this.color('primary'),
// 'colors.tertiary': this.color('primary'),
is_dark: {
get () { return this.settings['theme.is_dark'] },
set (value) {
this.$vuetify.theme.dark = value
this.setSetting({ key: 'theme.is_dark', value })
}
}
// 'colors[0]': {
// get () {
// return this.settings['theme.colors'] || [0, 0]
// },
// set (value) {
// console.error(value)
// if (!value) { return }
// this.setSetting({ key: 'theme.primary', value })
// if (this.settings['theme.is_dark']) {
// this.$vuetify.theme.themes.dark.primary = value
// } else {
// this.$vuetify.theme.themes.light.primary = value
// }
// }
// }
},
methods: {
...mapActions(['setSetting']),
reset () {
this.setSetting({ key: 'footerLinks', value: [{ href: '/about', label: 'about' }] })
},
forceLogoReload () {
this.$refs.upload.reset()
this.logoKey++
},
resetLogo (e) {
this.setSetting({ key: 'logo', value: null })
.then(this.forceLogoReload)
e.stopPropagation()
},
updateColor (i, v) {
this.colors[i] = v.hex
this.$vuetify.theme.themes.dark[i] = v.hex
},
openLinkModal () {
// this.link = { href: '', label: '' }
this.linkModal = true
this.$nextTick(() => this.$refs.linkModalForm.reset())
},
addFooterLink () {
const link = Object.assign({}, this.link)
this.setSetting({ key: 'footerLinks', value: this.settings.footerLinks.concat(link) })
// this.link = { href: '', label: '' }
this.$refs.linkModalForm.reset()
this.linkModal = false
},
async removeFooterLink (item) {
const ret = await this.$root.$confirm('admin.delete_footer_link_confirm')
if (!ret) { return }
const footerLinks = this.settings.footerLinks.filter(l => l.label !== item.label)
this.setSetting({ key: 'footerLinks', value: footerLinks })
},
editFooterLink (item) {
this.link = { href: item.href, label: item.label }
this.linkModal = true
},
async uploadLogo (file) {
const formData = new FormData()
formData.append('logo', file)
try {
await this.$axios.$post('/settings/logo', formData)
this.$root.$emit('message', {
message: 'Logo updated'
})
this.forceLogoReload()
} catch (e) {
}
},
save (key, value) {
if (this.settings[key] !== value) {
this.setSetting({ key, value })
}
}
}
}
</script>

View file

@ -1,87 +1,82 @@
<template lang="pug">
div
//- ADD NEW USER
el-collapse
el-collapse-item
template(slot='title')
el-button(mini size='mini') <v-icon name='plus'/> {{$t('common.new_user')}}
el-form(inline)
el-form-item(:label="$t('common.email')")
el-input(v-model='new_user.email')
el-form-item(:label="$t('common.admin')")
el-switch(v-model='new_user.is_admin')
el-button.float-right(@click='create_user' type='success' plain) {{$t('common.send')}}
el-alert.mb-1(type='info' show-icon :closable='false') {{$t('admin.user_add_help')}}
v-container
v-card-title {{$t('common.users')}}
v-spacer
v-text-field(v-model='search'
append-icon='mdi-magnify' outlined rounded
label='Search'
single-line hide-details)
//- USERS LIST
el-table(:data='paginatedUsers' small)
el-table-column(label='Email' width='250')
template(slot-scope='data')
el-popover(trigger='hover' :content='data.row.description' width='400')
span(slot='reference') {{data.row.email}}
el-table-column(:label="$t('common.actions')" width='300')
template(slot-scope='data')
div(v-if='data.row.id!==$auth.user.id')
el-button-group
el-button(size='mini'
:type='data.row.is_active?"warning":"success"'
@click='toggle(data.row)') {{data.row.is_active?$t('common.deactivate'):$t('common.activate')}}
el-button(size='mini'
:type='data.row.is_admin?"danger":"warning"'
@click='toggleAdmin(data.row)') {{data.row.is_admin?$t('admin.remove_admin'):$t('common.admin')}}
el-button(size='mini'
type='danger'
@click='delete_user(data.row)') {{$t('admin.delete_user')}}
div(v-else)
span {{$t('common.me')}}
client-only
el-pagination(:page-size='perPage' :currentPage.sync='userPage' :total='users_.length')
v-btn(color='primary' text @click='newUserDialog = true') <v-icon>mdi-plus</v-icon> {{$t('common.new_user')}}
//- ADD NEW USER
v-dialog(v-model='newUserDialog' :fullscreen="$vuetify.breakpoint.xsOnly")
v-card(color='secondary')
v-card-title {{$t('common.new_user')}}
v-card-text
v-form(v-model='valid' ref='user_form' lazy-validation @submit.prevent='createUser')
v-text-field(v-model='new_user.email'
:label="$t('common.email')"
:rules="$validators.email")
v-switch(v-model='new_user.is_admin' :label="$t('common.admin')" inset)
v-alert(type='info' :closable='false') {{$t('admin.user_add_help')}}
v-card-actions
v-spacer
v-btn(@click='newUserDialog=false' color='error') {{$t('common.cancel')}}
v-btn(@click='createUser' :disabled='!valid' color='primary') {{$t('common.send')}}
v-card-text
//- USERS LIST
v-data-table(
:headers='headers'
:items='users'
:hide-default-footer='users.length<5'
:search='search')
template(v-slot:item.actions='{item}')
v-btn(text small @click='toggle(item)'
:color='item.is_active?"warning":"success"') {{item.is_active?$t('common.disable'):$t('common.enable')}}
v-btn(text small @click='toggleAdmin(item)'
:color='item.is_admin?"warning":"error"') {{item.is_admin?$t('common.remove_admin'):$t('common.admin')}}
v-btn(text small @click='deleteUser(item)'
color='error') {{$t('admin.delete_user')}}
</template>
<script>
import { Message, MessageBox } from 'element-ui'
import { mapState } from 'vuex'
import get from 'lodash/get'
export default {
name: 'Users',
props: ['users'],
props: {
users: { type: Array, default: () => [] }
},
data () {
return {
perPage: 10,
userPage: 1,
newUserDialog: false,
valid: false,
new_user: {
email: '',
is_admin: false
},
users_: this.users
}
},
computed: {
...mapState(['settings']),
paginatedUsers () {
return this.users_.slice((this.userPage - 1) * this.perPage,
this.userPage * this.perPage)
search: '',
headers: [
{ value: 'email', text: 'Email' },
{ value: 'is_active', text: 'Active' },
{ value: 'actions', text: 'Actions', align: 'right' }
]
}
},
computed: mapState(['settings']),
methods: {
async delete_user (user) {
MessageBox.confirm(this.$t('admin.delete_user_confirm'),
this.$t('common.confirm'), {
confirmButtonText: this.$t('common.ok'),
cancelButtonText: this.$t('common.cancel'),
type: 'error'
})
.then(() => this.$axios.delete(`/user/${user.id}`))
.then(() => {
Message({
showClose: true,
type: 'success',
message: this.$t('admin.user_remove_ok')
})
this.users_ = this.users_.filter(u => u.id !== user.id)
})
async deleteUser (user) {
const ret = await this.$root.$confirm('admin.delete_user_confirm')
if (!ret) { return }
await this.$axios.delete(`/user/${user.id}`)
this.$root.$message('admin.user_remove_ok')
this.users_ = this.users_.filter(u => u.id !== user.id)
},
async toggle (user) {
toggle (user) {
user.is_active = !user.is_active
this.$axios.$put('/user', user)
},
@ -90,26 +85,22 @@ export default {
user.is_admin = !user.is_admin
await this.$axios.$put('/user', user)
} catch (e) {
console.error(e)
}
},
async create_user () {
async createUser () {
if (!this.$refs.user_form.validate()) { return }
try {
this.loading = true
const user = await this.$axios.$post('/user', this.new_user)
await this.$axios.$post('/user', this.new_user)
this.new_user = { email: '', is_admin: false }
Message({
showClose: true,
type: 'success',
message: this.$t('admin.user_create_ok')
})
this.users_.push(user)
this.$root.$message('admin.user_create_ok', { color: 'success' })
this.$emit('update')
this.loading = false
this.newUserDialog = false
} catch (e) {
Message({
showClose: true,
type: 'error',
message: this.$t(e)
})
const err = get(e, 'response.data.errors[0].message', e)
this.$root.$message(this.$t(err), { color: 'error' })
this.loading = false
}
}
}

View file

@ -1,4 +0,0 @@
export default [
'Europe/Rome',
'Europe/Paris'
]

57
docs/.api.md Normal file
View file

@ -0,0 +1,57 @@
## Add a new event
POST
{: .label .label-orange}
**`/event`**
> info "info"
> `Content-Type` has to be `multipart/form-data` 'cause support image upload
**Params**
| title | `string` | event's title |
| description | `string` | event's description (html accepted and sanitized) |
| place_name | `string` | the name of the place |
| place_address | `string` | the address of the place |
| start_datetime | `integer` | start timestamp |
| multidate | `integer` | is a multidate event? |
| tags | `array` | List of tags |
| recurrent | `object` | Recurrent event details |
| recurrent.frequency | `string` | could be `1w` or `2w` |
| recurrent.type | `string` | not used |
| recurrent.days | `array` | array of days |
| image | `image` | Image |
---
## Get current authenticated user
GET
{: .label .label-green}
**`/api/user`**
**Response**
```json
{
"description" : null,
"recover_code" : "",
"id" : 1,
"createdAt" : "2020-01-29T18:10:16.630Z",
"updatedAt" : "2020-01-30T22:42:14.789Z",
"is_active" : true,
"settings" : "{}",
"email" : "eventi@cisti.org",
"is_admin" : true
}
```
---

14
docs/.api_header.md Normal file
View file

@ -0,0 +1,14 @@
---
layout: default
title: API
permalink: /dev/api
parent: Hacking
nav_order: 8
---
1. TOC
{:toc}

8
docs/.api_helpers.js Normal file
View file

@ -0,0 +1,8 @@
exports.if_eq = function(a, b, opts) {
if (a == b) {
return opts.fn(this);
} else {
return opts.inverse(this);
}
}

34
docs/.api_template.hbs Normal file
View file

@ -0,0 +1,34 @@
{{#orphans}}
## {{description}}
{{type.names}}
{{#if_eq type.names 'POST'}}
{: .label .label-orange}
{{else}}
{: .label .label-green}
{{/if_eq}}
**`{{name}}`**
{{#each customTags}}
> {{tag}} "{{tag}}"
> {{{value}}}
{{/each}}
{{#if params}}
**Params**
{{#each params}}
| {{name}} | `{{type.names}}` | {{{description}}} |
{{/each}}
{{/if}}
{{#each examples}}
{{{this}}}
{{/each}}
---
{{/orphans}}

View file

@ -23,6 +23,7 @@ gem "mini_magick"
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.6"
gem "jemoji"
gem "premonition", "~> 2.0.0"
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem

View file

@ -66,6 +66,7 @@ GEM
mini_portile2 (~> 2.4.0)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
premonition (2.0.0)
public_suffix (3.1.1)
rake (12.3.1)
rb-fsevent (0.10.3)
@ -95,6 +96,7 @@ DEPENDENCIES
jemoji
just-the-docs
mini_magick
premonition (~> 2.0.0)
tzinfo (~> 1.2)
tzinfo-data
wdm (~> 0.1.0)

View file

@ -28,7 +28,7 @@ theme: "just-the-docs"
plugins:
- jekyll-feed
- jemoji
- premonition
search_enabled: true
@ -39,6 +39,8 @@ aux_links:
- https://framagit.org/les/gancio
"Forum":
- https://socialhub.activitypub.rocks/c/software/gancio
"Mastodon":
- https://mastodon.cisti.org/@gancio

View file

@ -0,0 +1,7 @@
---
layout: default
title: Add event
permalink: /usage/add_event
nav_order: 1
parent: Usage
---

View file

@ -7,8 +7,4 @@ nav_order: 4
# Usage
## Add event
### Normal
### Multidate
### Recurrent
ehmmm, help needed here :smile: feel free to send a PR => [here](https://framagit.org/les/gancio/tree/master/docs)

View file

@ -11,6 +11,8 @@
<link rel="shortcut icon" href="{{ "favicon.ico" | absolute_url }}" type="image/x-icon">
<link rel="stylesheet" href="{{ "/assets/css/just-the-docs.css" | absolute_url }}">
<link rel="stylesheet" href="{{ "/assets/css/style.css" | absolute_url }}">
<link rel="stylesheet" href="{{ "/assets/css/premonition.css" | absolute_url }}">
<link rel="stylesheet" href="{{ "/assets/css/fa.min.css" | absolute_url }}">
{% if site.search_enabled != nil %}
<script type="text/javascript" src="{{ "/assets/js/vendor/lunr.min.js" | absolute_url }}"></script>

View file

@ -1,328 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title> - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Gancio | A shared agenda for local communities with AP support</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Gancio" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/404.html" />
<meta property="og:url" content="https://gancio.org/404.html" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/404.html","headline":"Gancio","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link active"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<div id="main-content" class="page-content" role="main">
<style type="text/css" media="screen">
.container {
margin: 10px auto;
max-width: 600px;
text-align: center;
}
h1 {
margin: 30px 0;
font-size: 4em;
line-height: 1;
letter-spacing: -1px;
}
</style>
<div class="container">
<h1>404</h1>
<p><strong>Page not found :(</strong></p>
<p>The requested page could not be found.</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,318 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>About - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>About | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="About" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/about" />
<meta property="og:url" content="https://gancio.org/about" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/about","headline":"About","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/about" class="navigation-list-link active">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<div id="main-content" class="page-content" role="main">
<h2 id="about">About</h2>
<p>Gancio was born in Italy from political hacking movements, in particular from the <a href="https://autistici.org/underscore">hacklab underscore</a>.
We deal not only with technology but also with politics because we believe that technology is not neutral, that the Internet can also become an instrument of oppression, that information and software must be free and that knowledge is not for sale. For us, hacking is study and sharing, it is conscious and unconventional use of tools.</p>
<p>In 2018 we set up a “radical local server” <a href="https://cisti.org">cisti.org</a> that hosts services explicitly designed for local people / movements / groups / collectives and it is NOT our intention to grow. In fact, we believe that one of the main issues of technology is the scale.</p>
<p>We liked very much the idea of the federation and following the example of our brothers and sisters in bologna (the <a href="https://bida.im">bida.im</a> collective) we setup a mastodon instance as a first service.</p>
<p>The next step was to host a shared calendar, but as we didnt find anything that would fit, we decided to write it ourselves.</p>
</div>
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -1,12 +0,0 @@
.navigation-list-item {
font-size: 18px !important;
padding: 4px;
}
.navigation-list-item a {
color: blue;
}
.navigation-list-item a:hover {
color: black;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View file

@ -1 +0,0 @@
<svg width="28" height="28" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg"><title>Search</title><g fill-rule="nonzero" fill="#959396"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>

Before

Width:  |  Height:  |  Size: 444 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,176 +0,0 @@
// Event handling
function addEvent(el, type, handler) {
if (el.attachEvent) el.attachEvent('on'+type, handler); else el.addEventListener(type, handler);
}
function removeEvent(el, type, handler) {
if (el.detachEvent) el.detachEvent('on'+type, handler); else el.removeEventListener(type, handler);
}
// Show/hide mobile menu
function toggleNav(){
const nav = document.querySelector('.js-main-nav');
const auxNav = document.querySelector('.js-aux-nav');
const navTrigger = document.querySelector('.js-main-nav-trigger');
const search = document.querySelector('.js-search');
addEvent(navTrigger, 'click', function(){
var text = navTrigger.innerText;
var textToggle = navTrigger.getAttribute('data-text-toggle');
nav.classList.toggle('nav-open');
auxNav.classList.toggle('nav-open');
navTrigger.classList.toggle('nav-open');
search.classList.toggle('nav-open');
navTrigger.innerText = textToggle;
navTrigger.setAttribute('data-text-toggle', text);
textToggle = text;
})
}
// Site search
function initSearch() {
var index = lunr(function () {
this.ref('id');
this.field('title', { boost: 20 });
this.field('content', { boost: 10 });
this.field('url');
});
// Get the generated search_data.json file so lunr.js can search it locally.
sc = document.getElementsByTagName("script");
source = '';
for(idx = 0; idx < sc.length; idx++)
{
s = sc.item(idx);
if(s.src && s.src.match(/just-the-docs\.js$/))
{ source = s.src; }
}
jsPath = source.replace('just-the-docs.js', '');
jsonPath = jsPath + 'search-data.json';
var request = new XMLHttpRequest();
request.open('GET', jsonPath, true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
// Success!
var data = JSON.parse(request.responseText);
var keys = Object.keys(data);
for(var i in data) {
index.add({
id: data[i].id,
title: data[i].title,
content: data[i].content,
url: data[i].url
});
}
searchResults(data);
} else {
// We reached our target server, but it returned an error
console.log('Error loading ajax request. Request status:' + request.status);
}
};
request.onerror = function() {
// There was a connection error of some sort
console.log('There was a connection error');
};
request.send();
function searchResults(dataStore) {
var searchInput = document.querySelector('.js-search-input');
var searchResults = document.querySelector('.js-search-results');
var store = dataStore;
function hideResults() {
searchResults.innerHTML = '';
searchResults.classList.remove('active');
}
addEvent(searchInput, 'keyup', function(e){
var query = this.value;
searchResults.innerHTML = '';
searchResults.classList.remove('active');
if (query === '') {
hideResults();
} else {
var results = index.search(query);
if (results.length > 0) {
searchResults.classList.add('active');
var resultsList = document.createElement('ul');
searchResults.appendChild(resultsList);
for (var i in results) {
var resultsListItem = document.createElement('li');
var resultsLink = document.createElement('a');
var resultsUrlDesc = document.createElement('span');
var resultsUrl = store[results[i].ref].url;
var resultsRelUrl = store[results[i].ref].relUrl;
var resultsTitle = store[results[i].ref].title;
resultsLink.setAttribute('href', resultsUrl);
resultsLink.innerText = resultsTitle;
resultsUrlDesc.innerText = resultsRelUrl;
resultsList.classList.add('search-results-list');
resultsListItem.classList.add('search-results-list-item');
resultsLink.classList.add('search-results-link');
resultsUrlDesc.classList.add('fs-2','text-grey-dk-000','d-block');
resultsList.appendChild(resultsListItem);
resultsListItem.appendChild(resultsLink);
resultsLink.appendChild(resultsUrlDesc);
}
}
// When esc key is pressed, hide the results and clear the field
if (e.keyCode == 27) {
hideResults();
searchInput.value = '';
}
}
});
addEvent(searchInput, 'blur', function(){
setTimeout(function(){ hideResults() }, 300);
});
}
}
function pageFocus() {
var mainContent = document.querySelector('.js-main-content');
mainContent.focus();
}
// Document ready
function ready(){
toggleNav();
pageFocus();
if (typeof lunr !== 'undefined') {
initSearch();
}
}
// in case the document is already rendered
if (document.readyState!='loading') ready();
// modern browsers
else if (document.addEventListener) document.addEventListener('DOMContentLoaded', ready);
// IE <= 8
else document.attachEvent('onreadystatechange', function(){
if (document.readyState=='complete') ready();
});

View file

@ -1,101 +0,0 @@
{
"0": {
"id": "0",
"title": "",
"content": "404 Page not found :( The requested page could not be found.",
"url": "https://gancio.org/404.html",
"relUrl": "/404.html"
},
"1": {
"id": "1",
"title": "About",
"content": "About Gancio was born in Italy from political hacking movements, in particular from the hacklab underscore. We deal not only with technology but also with politics because we believe that technology is not neutral, that the Internet can also become an instrument of oppression, that information and software must be free and that knowledge is not for sale. For us, hacking is study and sharing, it is conscious and unconventional use of tools. In 2018 we set up a “radical local server” cisti.org that hosts services explicitly designed for local people / movements / groups / collectives and it is NOT our intention to grow. In fact, we believe that one of the main issues of technology is the scale. We liked very much the idea of the federation and following the example of our brothers and sisters in bologna (the bida.im collective) we setup a mastodon instance as a first service. The next step was to host a shared calendar, but as we didnt find anything that would fit, we decided to write it ourselves.",
"url": "https://gancio.org/about",
"relUrl": "/about"
},
"2": {
"id": "2",
"title": "Configuration",
"content": "Configuration Main gancio configuration is done with a configuration file. This shoud be a .json or a .js file and could be specified using the --config flag. eg. gancio start --config ./config.json eg. pm2 start gancio start -- --config ~/config.json Title Description BaseURL Server Database Upload path SMTP Admin_email Favicon User locale Secret Default settings Title The title will be in rss feed, in html head and in emails: &quot;title&quot;: &quot;Gancio&quot; Description &quot;description&quot;: &quot;a shared agenda for local communities&quot; BaseURL URL where your site will be accessible (include http or https): &quot;baseurl&quot;: &quot;https://gancio.cisti.org&quot; Server This probably support unix socket too :D &quot;server&quot;: { &quot;host&quot;: &quot;localhost&quot;, &quot;port&quot;: 13120 } Database DB configuration, look here for options. &quot;db&quot;: { &quot;dialect&quot;: &quot;sqlite&quot;, &quot;storage&quot;: &quot;/tmp/db.sqlite&quot; } Upload path Where to save images &quot;upload_path&quot;: &quot;./uploads&quot; SMTP SMTP configuration. Gancio should send emails at following events: the admin should receive emails of anon event (if enabled) to confirm them. the admin should receive emails of registration request (if enabled) to confirm them. an user should receive an email of registration requested. an user should receive an email of confirmed registration. an user should receive a confirmation email when subscribed directly by admin. &quot;smtp&quot;: { &quot;auth&quot;: { &quot;user&quot;: &quot;&quot;, &quot;pass&quot;: &quot;&quot; }, &quot;secure&quot;: true, &quot;host&quot;: &quot;&quot; } Admin_email Email of administrator. Note that email from gancio comes from this email and that the SMTP configuration above should allow to use this address as from. Favicon You could specify another favicon. This is also used as logo (top-left corner): &quot;favicon&quot;: &quot;./favicon.ico&quot; User locale Probably you want to modify some text for your specific community, thats why we thought the user_locale configuration: you can specify your version of each string of gancio making a directory with your locales inside. For example, lets say you want to modify the text inside the /about page: mkdir /opt/gancio/user_locale put something like this in /opt/gancio/user_locale/en.js to override the about in english: export default { about: &#39;A new about&#39; } and then point the user_locale configuration to that directory: &quot;user_locale&quot;: &quot;/opt/gancio/user_locale&quot; Watch here for a list of strings you can override. :warning: Note that a restart is needed when you change user_locales content. Secret Default settings { &quot;title&quot;: &quot;Gancio&quot;, &quot;description&quot;: &quot;A shared agenda for local communities&quot;, &quot;baseurl&quot;: &quot;http://localhost:13120&quot;, &quot;server&quot;: { &quot;host&quot;: &quot;0.0.0.0&quot;, &quot;port&quot;: 13120 }, &quot;db&quot;: { &quot;dialect&quot;: &quot;sqlite&quot;, &quot;storage&quot;: &quot;/tmp/db.sqlite&quot; }, &quot;upload_path&quot;: &quot;./&quot;, &quot;favicon&quot;: &quot;../dist/favicon.ico&quot;, &quot;smtp&quot;: { &quot;auth&quot;: { &quot;user&quot;: &quot;&quot;, &quot;pass&quot;: &quot;&quot; }, &quot;secure&quot;: true, &quot;host&quot;: &quot;&quot; }, &quot;admin_email&quot;: &quot;&quot;, &quot;secret&quot;: &quot;notsosecret&quot; }",
"url": "https://gancio.org/config",
"relUrl": "/config"
},
"3": {
"id": "3",
"title": "Debian",
"content": "Debian installation Install Node.js &amp; yarn (from root) curl -sL https://deb.nodesource.com/setup_12.x | bash - apt-get install -y nodejs curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - echo &quot;deb https://dl.yarnpkg.com/debian/ stable main&quot; &gt; /etc/apt/sources.list.d/yarn.list apt-get update &amp;&amp; apt-get install yarn source Install Gancio yarn global add gancio --prod Setup with postgreSQL (optional as you can choose sqlite) apt-get install postgresql # Create the database su postgres -c psql postgres=# create database gancio; postgres=# create user gancio with encrypted password &#39;gancio&#39;; postgres=# grant all privileges on database gancio to gancio; Create a user to run gancio from adduser gancio su gancio Launch interactive setup gancio setup --config config.json Start gancio start --config config.json Point your web browser to http://localhost:13120 or where you selected during setup. Setup nginx as a proxy To deploy gancio in production you should use something like pm2: sudo yarn global add pm2 pm2 start gancio -- --config config.json # Run this command to run your application as a service and automatically restart after a reboot: pm2 startup # read the output! sudo pm2 startup -u gancio Upgrade sudo yarn global add gancio sudo service pm2 restart",
"url": "https://gancio.org/install/debian",
"relUrl": "/install/debian"
},
"4": {
"id": "4",
"title": "Hacking",
"content": "Development Stack Gancio is built with following technologies: Nuxt.js Vue.js Express Node.js Sequelize Element.ui Testing on your own machine Download source git clone https://framagit.org/les/gancio Install dependencies yarn Hacking yarn dev Please use the issue board and the forum to discuss any modification.",
"url": "https://gancio.org/dev",
"relUrl": "/dev"
},
"5": {
"id": "5",
"title": "Docker",
"content": "Initial setup Use sqlite Use postgreSQL Start gancio Upgrade Initial setup You do not need to clone the full repo as we distribute gancio via npm. A Dockerfile and a docker-compose.yml are the only files needed. Create a directory where everything related to gancio is stored (db, images, config) mkdir /opt/gancio cd /opt/gancio note that you can choose a different directory. Use sqlite Download docker-compose.yml and Dockerfile wget https://gancio.org/docker/Dockerfile wget https://gancio.org/docker/sqlite/docker-compose.yml Create an empty db and config (this is needed) touch config.json db.sqlite mkdir user_locale Build docker image and launch interactive setup in one step docker-compose build docker-compose run --rm gancio gancio setup --docker --db=sqlite Use postgreSQL Download docker-compose.yml and Dockerfile wget https://gancio.org/docker/Dockerfile wget https://gancio.org/docker/postgres/docker-compose.yml Create an empty configuration (this is needed) touch config.json mkdir user_locale Build docker image and launch interactive setup in one step docker-compose build docker-compose run --rm gancio gancio setup --docker --db=postgres Start gancio Run your container docker-compose up -d Look at logs with docker-compose logs Setup nginx as a proxy Point your web browser to http://localhost:13120 or where you specified during setup and enjoy :tada: You can edit config.json file and restart the container on your needs, see Configuration for more details. Upgrade cd /opt/gancio docker-compose up -d --no-deps --build",
"url": "https://gancio.org/install/docker",
"relUrl": "/install/docker"
},
"6": {
"id": "6",
"title": "Federation",
"content": "Federation Each instance has only one AP Actor that publishes each event. We are considering the introduction of other “Actor” but they will not be linked to users, rather to places or tags/categories. There are no personal homes with a timeline of people I follow, everyone has a sort of local timeline of the instance, its an anti filter-bubble feature. Events are not published with the type Event but with type Note because we wanted to add the possibility to interact with events from mastodon instances (boost / bookmark and “comments” that we call resources because we dont want it to become a place of debate, but more a place where to keep a historical memory of events, e.g. an audio recording of a talk). When mastodon will support Event object type we will change for sure.",
"url": "https://gancio.org/federation",
"relUrl": "/federation"
},
"7": {
"id": "7",
"title": "Home",
"content": "Gancio A shared agenda for local communities. Get started now Demo Source Some relevant key features: Focus on content not on people: nowhere on gancio appears the identity of who published the event, not even under a nickname, not even to administrators (except in the db). This is not an ego-friendly platform. Visitors first. We do not want logged user to get more features than random visitor. We do not want users to register, except to publish events and even in this case you can publish an anonymous event. Anonymous events: optionally a visitor can create events without being registered (an administrator has to confirm them) We are not interested in making hits so we export events in many ways, via RSS feeds, via global or individual ics, incorporating lists of events or single event via iframe on other websites. Very easy UI Multidays events support (festival, conferences…) Recurrent events support (each monday, each two monday, each monday and friday, each two saturday, etc.) Filters events for tags or places RSS and ICS export (with filters) embeddable iframe (example) boost / bookmark / comment events from the fediverse! Lot of configurations available (user registration open/close, enable federation, enable recurrent events) License Gancio is distributed by an AGPL-3.0 Licence.",
"url": "https://gancio.org/",
"relUrl": "/"
},
"8": {
"id": "8",
"title": "Install",
"content": "Install (production) Install on Debian Install using docker Post installation Nginx as a proxy If you wanna hack or run the current develop release take a look at Hacking &amp; contribute",
"url": "https://gancio.org/install",
"relUrl": "/install"
},
"9": {
"id": "9",
"title": "Instances",
"content": "Instances gancio.cisti.org (Torino, Italy) lapunta.org (Firenze, Italy)",
"url": "https://gancio.org/instances",
"relUrl": "/instances"
},
"10": {
"id": "10",
"title": "Support a new language",
"content": "Add a new locale watch this commit",
"url": "https://gancio.org/dev/locales",
"relUrl": "/dev/locales"
},
"11": {
"id": "11",
"title": "Migration",
"content": "If you need to modify the dbs structure while hacking, just change server/api/models/ and remember to create a migration, to understand how things works check the sequelize documentation",
"url": "https://gancio.org/dev/migration",
"relUrl": "/dev/migration"
},
"12": {
"id": "12",
"title": "Nginx",
"content": "Nginx proxy configuration This is the default nginx configuration for gancio, please modify at least the server_name and ssl_certificates path. Note that this does not include a cache configuration and that gancio does not use a cache control at all, if you can help with this task youre welcome. server { listen 80; listen [::]:80; server_name gancio.cisti.org; root /var/www/letsencrypt; location /.well-known/acme-challenge/ { allow all; } location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name gancio.cisti.org; ssl_protocols TLSv1.2; ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; # Uncomment these lines once you acquire a certificate: # ssl_certificate /etc/letsencrypt/live/gancio.cisti.org/fullchain.pem; # ssl_certificate_key /etc/letsencrypt/live/gancio.cisti.org/privkey.pem; keepalive_timeout 70; sendfile on; client_max_body_size 80m; gzip on; gzip_disable &quot;msie6&quot;; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_buffers 16 8k; gzip_http_version 1.1; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; add_header Strict-Transport-Security &quot;max-age=31536000&quot;; location / { try_files $uri @proxy; } location @proxy { proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto https; proxy_set_header Proxy &quot;&quot;; proxy_pass_header Server; proxy_pass http://127.0.0.1:13120; proxy_buffering on; proxy_redirect off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; tcp_nodelay on; } }",
"url": "https://gancio.org/install/nginx",
"relUrl": "/install/nginx"
},
"13": {
"id": "13",
"title": "Project Structure",
"content": "Project structure API / backend Client / frontend Federation / ActivityPub API / backend Source code inside server/api/. index.js is basically a routing table pointing each PATH with specified HTTP VERB to a method of a controller. jwt is used to authenticate api request. Express.js is based on middleware, passing each request to a chain of methods. If you come from a PHP background, note that the main difference with Node.js is that the server process is always running and able to manage multiple requests and tasks together (asyncronically) while each php process is tied to a single request. Sequelize is used as ORM. Take a look in /server/api/models. Client / frontend Nuxt.js is used here! Nuxt is basically Vue plus SSR (Server Side Rendering). Client routing in nuxt is automatic (if you dont need something special), just put your page inside pages and thats it! Federation / ActivityPub Code inside server/federation.",
"url": "https://gancio.org/dev/structure",
"relUrl": "/dev/structure"
}
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -1,472 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Configuration - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Configuration | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Configuration" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/config" />
<meta property="og:url" content="https://gancio.org/config" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/config","headline":"Configuration","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/config" class="navigation-list-link active">Configuration</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewbox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title>
<g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"></path><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"></path></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<div id="main-content" class="page-content" role="main">
<h2 class="no_toc" id="configuration">Configuration</h2>
<p>Main <code class="highlighter-rouge">gancio</code> configuration is done with a configuration file.
This shoud be a <code class="highlighter-rouge">.json</code> or a <code class="highlighter-rouge">.js</code> file and could be specified using the <code class="highlighter-rouge">--config</code> flag.</p>
<ul>
<li><small>eg. <code class="highlighter-rouge">gancio start --config ./config.json</code></small></li>
<li><small>eg. <code class="highlighter-rouge">pm2 start gancio start -- --config ~/config.json</code></small></li>
</ul>
<ol id="markdown-toc">
<li><a href="#title" id="markdown-toc-title">Title</a></li>
<li><a href="#description" id="markdown-toc-description">Description</a></li>
<li><a href="#baseurl" id="markdown-toc-baseurl">BaseURL</a></li>
<li><a href="#server" id="markdown-toc-server">Server</a></li>
<li><a href="#database" id="markdown-toc-database">Database</a></li>
<li><a href="#upload-path" id="markdown-toc-upload-path">Upload path</a></li>
<li><a href="#smtp" id="markdown-toc-smtp">SMTP</a></li>
<li><a href="#admin_email" id="markdown-toc-admin_email">Admin_email</a></li>
<li><a href="#favicon" id="markdown-toc-favicon">Favicon</a></li>
<li><a href="#user-locale" id="markdown-toc-user-locale">User locale</a></li>
<li><a href="#secret" id="markdown-toc-secret">Secret</a></li>
<li><a href="#default-settings" id="markdown-toc-default-settings">Default settings</a></li>
</ol>
<ul>
<li>
<h3 id="title">Title</h3>
<p>The title will be in rss feed, in html head and in emails:</p>
</li>
</ul>
<p><code class="highlighter-rouge">"title": "Gancio"</code></p>
<p><img src="assets/title.png" alt="title"></p>
<ul>
<li>
<h3 id="description">Description</h3>
<p><code class="highlighter-rouge">"description": "a shared agenda for local communities"</code></p>
</li>
<li>
<h3 id="baseurl">BaseURL</h3>
<p>URL where your site will be accessible (include http or https):<br>
<code class="highlighter-rouge">"baseurl": "https://gancio.cisti.org"</code></p>
</li>
<li>
<h3 id="server">Server</h3>
<p>This probably support unix socket too :D</p>
</li>
</ul>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"server"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"host"</span><span class="p">:</span><span class="w"> </span><span class="s2">"localhost"</span><span class="p">,</span><span class="w">
</span><span class="s2">"port"</span><span class="p">:</span><span class="w"> </span><span class="mi">13120</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<ul>
<li>
<h3 id="database">Database</h3>
<p>DB configuration, look <a href="https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#instance-constructor-constructor">here</a> for options.</p>
<div class="language-json highlighter-rouge">
<div class="highlight"><pre class="highlight"><code><span class="s2">"db"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"dialect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"sqlite"</span><span class="p">,</span><span class="w">
</span><span class="s2">"storage"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/tmp/db.sqlite"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div> </div>
</li>
<li>
<h3 id="upload-path">Upload path</h3>
<p>Where to save images
<code class="highlighter-rouge">"upload_path": "./uploads"</code></p>
</li>
<li>
<h3 id="smtp">SMTP</h3>
<p>SMTP configuration.
Gancio should send emails at following events:</p>
</li>
<li>the admin should receive emails of anon event (if enabled) to confirm them.</li>
<li>the admin should receive emails of registration request (if enabled) to confirm them.</li>
<li>an user should receive an email of registration requested.</li>
<li>an user should receive an email of confirmed registration.</li>
<li>an user should receive a confirmation email when subscribed directly by admin.</li>
</ul>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"smtp"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"auth"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"user"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
</span><span class="s2">"pass"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="s2">"secure"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
</span><span class="s2">"host"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<ul>
<li>
<h3 id="admin_email">Admin_email</h3>
<p>Email of administrator. Note that email from gancio comes from this email and that
the SMTP configuration above should allow to use this address as from.</p>
</li>
<li>
<h3 id="favicon">Favicon</h3>
<p>You could specify another favicon. This is also used as logo (top-left
corner): <br>
<code class="highlighter-rouge">"favicon": "./favicon.ico"</code></p>
</li>
<li>
<h3 id="user-locale">User locale</h3>
<p>Probably you want to modify some text for your specific community, thats
why we thought the <code class="highlighter-rouge">user_locale</code> configuration: you can specify your version of
each string of <strong>gancio</strong> making a directory with your locales inside.
For example, lets say you want to modify the text inside the <code class="highlighter-rouge">/about</code>
page:<br>
<code class="highlighter-rouge">mkdir /opt/gancio/user_locale</code>
put something like this in <code class="highlighter-rouge">/opt/gancio/user_locale/en.js</code> to override the about in
english:</p>
<div class="language-js highlighter-rouge">
<div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="k">default</span> <span class="p">{</span>
<span class="na">about</span><span class="p">:</span> <span class="dl">'</span><span class="s1">A new about</span><span class="dl">'</span>
<span class="p">}</span>
</code></pre></div> </div>
<p>and then point the <code class="highlighter-rouge">user_locale</code> configuration to that directory:</p>
<div class="language-json highlighter-rouge">
<div class="highlight"><pre class="highlight"><code><span class="s2">"user_locale"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/opt/gancio/user_locale"</span><span class="w">
</span></code></pre></div> </div>
<p>Watch <a href="https://framagit.org/les/gancio/tree/master/locales">here</a> for a
list of strings you can override.<br>
<small><img class="emoji" title=":warning:" alt=":warning:" src="https://github.githubassets.com/images/icons/emoji/unicode/26a0.png" height="20" width="20"> Note that a restart is needed when you change
user_locales content.</small></p>
</li>
<li>
<h3 id="secret">Secret</h3>
</li>
</ul>
<h2 id="default-settings">Default settings</h2>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="s2">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Gancio"</span><span class="p">,</span><span class="w">
</span><span class="s2">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"A shared agenda for local communities"</span><span class="p">,</span><span class="w">
</span><span class="s2">"baseurl"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://localhost:13120"</span><span class="p">,</span><span class="w">
</span><span class="s2">"server"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"host"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0.0.0.0"</span><span class="p">,</span><span class="w">
</span><span class="s2">"port"</span><span class="p">:</span><span class="w"> </span><span class="mi">13120</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="s2">"db"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"dialect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"sqlite"</span><span class="p">,</span><span class="w">
</span><span class="s2">"storage"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/tmp/db.sqlite"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="s2">"upload_path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"./"</span><span class="p">,</span><span class="w">
</span><span class="s2">"favicon"</span><span class="p">:</span><span class="w"> </span><span class="s2">"../dist/favicon.ico"</span><span class="p">,</span><span class="w">
</span><span class="s2">"smtp"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"auth"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"user"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
</span><span class="s2">"pass"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="s2">"secure"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
</span><span class="s2">"host"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="s2">"admin_email"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
</span><span class="s2">"secret"</span><span class="p">:</span><span class="w"> </span><span class="s2">"notsosecret"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,394 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Hacking - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Hacking | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Hacking" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/dev" />
<meta property="og:url" content="https://gancio.org/dev" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/dev","headline":"Hacking","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/dev" class="navigation-list-link active">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<div id="main-content" class="page-content" role="main">
<h3 id="development-stack">Development Stack</h3>
<p><strong>Gancio</strong> is built with following technologies:</p>
<ul>
<li><a href="https://nuxtjs.org/">Nuxt.js</a></li>
<li><a href="https://vuejs.org/">Vue.js</a></li>
<li>Express</li>
<li>Node.js</li>
<li><a href="https://sequelize.org/">Sequelize</a></li>
<li>Element.ui</li>
</ul>
<h3 id="testing-on-your-own-machine">Testing on your own machine</h3>
<ol>
<li>Download source
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://framagit.org/les/gancio
</code></pre></div> </div>
</li>
<li>Install dependencies
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yarn
</code></pre></div> </div>
</li>
<li>Hacking
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yarn dev
</code></pre></div> </div>
</li>
</ol>
<p>Please use the <a href="https://framagit.org/les/gancio/-/boards">issue board</a> and the <a href="https://framavox.org/g/hMXTDgtJ/gancio">forum</a> to discuss any modification.</p>
<hr>
<h2 class="text-delta">Table of contents</h2>
<ul>
<li>
<a href="https://gancio.org/dev/locales">Support a new language</a>
</li>
<li>
<a href="https://gancio.org/dev/migration">Migration</a>
</li>
<li>
<a href="https://gancio.org/dev/structure">Project Structure</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,319 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Support a new language - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Support a new language | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Support a new language" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/dev/locales" />
<meta property="og:url" content="https://gancio.org/dev/locales" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/dev/locales","headline":"Support a new language","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item active">
<a href="https://gancio.org/dev/locales" class="navigation-list-link active">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<nav class="breadcrumb-nav">
<ol class="breadcrumb-nav-list">
<li class="breadcrumb-nav-list-item"><a href="https://gancio.org/dev">Hacking</a></li>
<li class="breadcrumb-nav-list-item"><span>Support a new language</span></li>
</ol>
</nav>
<div id="main-content" class="page-content" role="main">
<h3 id="add-a-new-locale">Add a new locale</h3>
<p>watch <a href="https://framagit.org/les/gancio/commit/cd95c7eb3b9e4bc4832a7b33d8d79b4fd3cbda2d">this commit</a></p>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,320 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Migration - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Migration | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Migration" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/dev/migration" />
<meta property="og:url" content="https://gancio.org/dev/migration" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/dev/migration","headline":"Migration","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/dev/migration" class="navigation-list-link active">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<nav class="breadcrumb-nav">
<ol class="breadcrumb-nav-list">
<li class="breadcrumb-nav-list-item"><a href="https://gancio.org/dev">Hacking</a></li>
<li class="breadcrumb-nav-list-item"><span>Migration</span></li>
</ol>
</nav>
<div id="main-content" class="page-content" role="main">
<p>If you need to modify the dbs structure while hacking, just change <code class="highlighter-rouge">server/api/models/</code> and
remember to create a migration, to understand how things works <a href="https://sequelize.org/master/manual/migrations.html">check the sequelize documentation</a></p>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,349 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Project Structure - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Project Structure | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Project Structure" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/dev/structure" />
<meta property="og:url" content="https://gancio.org/dev/structure" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/dev/structure","headline":"Project Structure","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/dev/structure" class="navigation-list-link active">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<nav class="breadcrumb-nav">
<ol class="breadcrumb-nav-list">
<li class="breadcrumb-nav-list-item"><a href="https://gancio.org/dev">Hacking</a></li>
<li class="breadcrumb-nav-list-item"><span>Project Structure</span></li>
</ol>
</nav>
<div id="main-content" class="page-content" role="main">
<h3 class="no_toc" id="project-structure">Project structure</h3>
<ol id="markdown-toc">
<li><a href="#api--backend" id="markdown-toc-api--backend">API / backend</a></li>
<li><a href="#client--frontend" id="markdown-toc-client--frontend">Client / frontend</a></li>
<li><a href="#federation--activitypub" id="markdown-toc-federation--activitypub">Federation / ActivityPub</a></li>
</ol>
<h3 id="api--backend">API / backend</h3>
<p>Source code inside <code class="highlighter-rouge">server/api/</code>.<br />
<code class="highlighter-rouge">index.js</code> is basically a routing table pointing each PATH with specified
HTTP VERB to a method of a controller.</p>
<p>jwt is used to authenticate api request.</p>
<p><a href="https://expressjs.com/">Express.js</a> is based on middleware, passing each request to a chain of methods.</p>
<p>If you come from a PHP background, note that the main difference with
<a href="https://en.wikipedia.org/wiki/Node.js">Node.js</a> is that the server process is always running and able to manage
multiple requests and tasks together (asyncronically) while each php
process is tied to a single request.</p>
<p><a href="https://sequelize.org/">Sequelize</a> is used as ORM. Take a look in <a href="https://framagit.org/les/gancio/tree/master/server/api/models"><code class="highlighter-rouge">/server/api/models</code></a>.</p>
<h3 id="client--frontend">Client / frontend</h3>
<p>Nuxt.js is used here!<br />
Nuxt is basically Vue plus SSR (Server Side Rendering).
Client routing in nuxt is automatic (if you dont need something special),
just put your page inside <code class="highlighter-rouge">pages</code> and thats it!</p>
<h3 id="federation--activitypub">Federation / ActivityPub</h3>
<p>Code inside <a href="https://framagit.org/les/gancio/tree/master/server/federation"><code class="highlighter-rouge">server/federation</code></a>.</p>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,3 +0,0 @@
FROM node:latest
WORKDIR /
RUN yarn global add gancio

View file

@ -1,31 +0,0 @@
version: '3'
services:
db:
image: postgres
container_name: postgres
volumes:
- db:/var/lib/postgres
- /etc/localtime:/etc/localtime:ro
environment:
- POSTGRES_USER=gancio
- POSTGRES_DB=gancio
- POSTGRES_PASSWORD=gancio
restart: always
ports:
- 5432:5432
gancio:
build: .
image: node:latest
environment:
- DEBUG=*,-babel,-follow-redirects,-send,-body-parser:*,-express:*,-connect:*,-sequelize:*
container_name: gancio
restart: always
command: gancio start --docker --db=postgres
volumes:
- ./config.json:/opt/gancio/config.json
- ./uploads:/opt/gancio/uploads
depends_on:
- db
ports:
- "localhost:13120:13120"

View file

@ -1,17 +0,0 @@
version: '3'
services:
gancio:
build: .
restart: always
image: node:latest
container_name: gancio
command: gancio start --docker --db=sqlite
environment:
- DEBUG=*,-babel,-follow-redirects,-send,-body-parser:*,-express:*,-connect:*,-sequelize:*
volumes:
- ./db.sqlite:/opt/gancio/db.sqlite
- ./config.json:/opt/gancio/config.json
- ./uploads:/opt/gancio/uploads
ports:
- "127.0.0.1:13120:13120"

View file

@ -1,317 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Federation - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Federation | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Federation" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/federation" />
<meta property="og:url" content="https://gancio.org/federation" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/federation","headline":"Federation","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/federation" class="navigation-list-link active">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<div id="main-content" class="page-content" role="main">
<h2 id="federation">Federation</h2>
<p>Each instance has only one <a href="https://www.w3.org/TR/activitypub/#actors">AP Actor</a> that publishes each event.
We are considering the introduction of other “Actor” but they will not be linked to users, rather to places or tags/categories.
There are no personal homes with a timeline of people I follow, everyone has a sort of local timeline of the instance, its an anti filter-bubble feature.</p>
<p>Events are not published with the type <code class="highlighter-rouge">Event</code> but with type <code class="highlighter-rouge">Note</code> because we wanted to add the possibility to interact with events from mastodon instances (boost / bookmark and “comments” that we call resources because we dont want it to become a place of debate, but more a place where to keep a historical memory of events, e.g. an audio recording of a talk).</p>
<p>When mastodon will support <code class="highlighter-rouge">Event</code> object type we will change for sure.</p>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.6">Jekyll</generator><link href="https://gancio.org/feed.xml" rel="self" type="application/atom+xml" /><link href="https://gancio.org/" rel="alternate" type="text/html" /><updated>2019-12-06T00:50:52+01:00</updated><id>https://gancio.org/feed.xml</id><title type="html">Gancio</title><subtitle>A shared agenda for local communities with AP support</subtitle></feed>

View file

@ -1,349 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Home - Gancio</title>
<meta name="Description" content="Gancio is a shared agenda for local communities.">
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Home | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Home" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="Gancio is a shared agenda for local communities." />
<meta property="og:description" content="Gancio is a shared agenda for local communities." />
<link rel="canonical" href="https://gancio.org/" />
<meta property="og:url" content="https://gancio.org/" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebSite","url":"https://gancio.org/","name":"Gancio","headline":"Home","description":"Gancio is a shared agenda for local communities.","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/" class="navigation-list-link active">Home</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<div id="main-content" class="page-content" role="main">
<h1 class="fs-9" id="-gancio"><img src="https://git.lattuga.net/repo-avatars/476" width="60px" /> Gancio</h1>
<p class="fs-6">A shared agenda for local communities.</p>
<p><a href="install" class="btn btn-primary fs-5 mb-4 mb-md-0 mr-2">Get started now</a> <a href="https://demo.gancio.org" class="btn btn-green fs-5 mb-4 mb-md-0">Demo</a>
<a href="https://framagit.org/les/gancio" class="btn fs-5">Source</a></p>
<p><a href="assets/home1.png" data-fancybox="group" data-caption="Home of the first gancio instance"><img src="assets/thumbs/home1.png" alt="assets/thumbs/home1.png" /></a>
<a href="assets/mobile1.png" data-fancybox="group" data-caption="Home mobile"><img src="assets/thumbs/mobile1.png" alt="assets/thumbs/mobile1.png" /></a>
<a href="assets/mobile2.png" data-fancybox="group" data-caption="Home mobile"><img src="assets/thumbs/mobile2.png" alt="assets/thumbs/mobile2.png" /></a>
<a href="assets/admin_users.png" data-fancybox="group" data-caption="Admin interface"><img src="assets/thumbs/admin_users.png" alt="assets/thumbs/admin_users.png" /></a></p>
<h2 id="some-relevant-key-features">Some relevant key features:</h2>
<ul>
<li>
<p><strong>Focus on content</strong> not on people:
nowhere on gancio appears the identity of who published the event, not even under a nickname, not even to administrators (except in the db). This is not an ego-friendly platform.</p>
</li>
<li>
<p><strong>Visitors first</strong>. We do not want logged user to get more features than random visitor. We do not want users to register, except to publish events and even in this case you can publish an anonymous event.</p>
</li>
<li>
<p><strong>Anonymous events</strong>: optionally a visitor can create events without being registered (an administrator has to confirm them)</p>
</li>
<li>
<p><strong>We are not interested in making hits</strong> so we export events in many ways, via RSS feeds, via global or individual ics, incorporating lists of events or single event via iframe on other websites.</p>
</li>
<li>Very easy UI</li>
<li>Multidays events support (festival, conferences…)</li>
<li>Recurrent events support (each monday, each two monday, each monday and friday, each two saturday, etc.)</li>
<li>Filters events for tags or places</li>
<li>RSS and ICS export (with filters)</li>
<li>embeddable iframe (<a href="https://gancio.cisti.org/embed/list?title=Upcoming events">example</a>)</li>
<li>boost / bookmark / comment events from the fediverse!</li>
<li>Lot of configurations available (user registration open/close, enable federation, enable recurrent events)</li>
</ul>
<h3 id="license">License</h3>
<p>Gancio is distributed by an <a href="https://www.gnu.org/licenses/agpl-3.0.en.html">AGPL-3.0 Licence</a>.</p>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,321 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Install - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Install | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Install" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/install" />
<meta property="og:url" content="https://gancio.org/install" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/install","headline":"Install","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/install" class="navigation-list-link active">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<div id="main-content" class="page-content" role="main">
<h2 id="install-production">Install (production)</h2>
<ul>
<li><a href="/install/debian">Install on Debian</a></li>
<li><a href="/install/docker">Install using docker</a></li>
</ul>
<h3 id="post-installation">Post installation</h3>
<ul>
<li><a href="/install/nginx">Nginx as a proxy</a></li>
</ul>
<p>If you wanna hack or run the current develop release take a look at <a href="../dev">Hacking &amp; contribute</a></p>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,379 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Debian - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Debian | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Debian" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/install/debian" />
<meta property="og:url" content="https://gancio.org/install/debian" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/install/debian","headline":"Debian","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item active">
<a href="https://gancio.org/install/debian" class="navigation-list-link active">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<nav class="breadcrumb-nav">
<ol class="breadcrumb-nav-list">
<li class="breadcrumb-nav-list-item"><a href="https://gancio.org/install">Install</a></li>
<li class="breadcrumb-nav-list-item"><span>Debian</span></li>
</ol>
</nav>
<div id="main-content" class="page-content" role="main">
<h2 id="debian-installation">Debian installation</h2>
<ol>
<li>Install Node.js &amp; yarn (<strong>from root</strong>)
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-sL</span> https://deb.nodesource.com/setup_12.x | bash -
apt-get <span class="nb">install</span> <span class="nt">-y</span> nodejs
curl <span class="nt">-sL</span> https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
<span class="nb">echo</span> <span class="s2">"deb https://dl.yarnpkg.com/debian/ stable main"</span> <span class="o">&gt;</span> /etc/apt/sources.list.d/yarn.list
apt-get update <span class="o">&amp;&amp;</span> apt-get <span class="nb">install </span>yarn
</code></pre></div> </div>
<p><small><a href="https://github.com/nodesource/distributions/blob/master/README.md">source</a></small></p>
</li>
<li>Install Gancio
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yarn global add gancio <span class="nt">--prod</span>
</code></pre></div> </div>
</li>
<li>Setup with postgreSQL <strong>(optional as you can choose sqlite)</strong>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt-get <span class="nb">install </span>postgresql
<span class="c"># Create the database</span>
su postgres <span class="nt">-c</span> psql
<span class="nv">postgres</span><span class="o">=</span><span class="c"># create database gancio;</span>
<span class="nv">postgres</span><span class="o">=</span><span class="c"># create user gancio with encrypted password 'gancio';</span>
<span class="nv">postgres</span><span class="o">=</span><span class="c"># grant all privileges on database gancio to gancio;</span>
</code></pre></div> </div>
</li>
<li>Create a user to run gancio from
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adduser gancio
su gancio
</code></pre></div> </div>
</li>
<li>Launch interactive setup
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gancio setup <span class="nt">--config</span> config.json
</code></pre></div> </div>
</li>
<li>Start
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gancio start <span class="nt">--config</span> config.json
</code></pre></div> </div>
</li>
<li>
<p>Point your web browser to <a href="http://localhost:13120">http://localhost:13120</a> or where you selected during setup.</p>
</li>
<li>
<p><a href="/install/nginx">Setup nginx as a proxy</a></p>
</li>
<li>To deploy gancio in production you should use something like <strong><a href="http://pm2.keymetrics.io/">pm2</a></strong>:</li>
</ol>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>yarn global add pm2
pm2 start gancio <span class="nt">--</span> <span class="nt">--config</span> config.json
<span class="c"># Run this command to run your application as a service and automatically restart after a reboot:</span>
pm2 startup <span class="c"># read the output!</span>
<span class="nb">sudo </span>pm2 startup <span class="nt">-u</span> gancio
</code></pre></div></div>
<ol>
<li>Upgrade
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>yarn global add gancio
<span class="nb">sudo </span>service pm2 restart
</code></pre></div> </div>
</li>
</ol>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,421 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Docker - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Docker | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Docker" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/install/docker" />
<meta property="og:url" content="https://gancio.org/install/docker" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/install/docker","headline":"Docker","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/install/docker" class="navigation-list-link active">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewbox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title>
<g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"></path><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"></path></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<nav class="breadcrumb-nav">
<ol class="breadcrumb-nav-list">
<li class="breadcrumb-nav-list-item"><a href="https://gancio.org/install">Install</a></li>
<li class="breadcrumb-nav-list-item"><span>Docker</span></li>
</ol>
</nav>
<div id="main-content" class="page-content" role="main">
<h2 class="no_toc text-delta" id="table-of-contents">Table of contents</h2>
<ol id="markdown-toc">
<li><a href="#initial-setup" id="markdown-toc-initial-setup">Initial setup</a></li>
<li><a href="#use-sqlite" id="markdown-toc-use-sqlite">Use sqlite</a></li>
<li><a href="#use-postgresql" id="markdown-toc-use-postgresql">Use postgreSQL</a></li>
<li><a href="#start-gancio" id="markdown-toc-start-gancio">Start gancio</a></li>
<li><a href="#upgrade" id="markdown-toc-upgrade">Upgrade</a></li>
</ol>
<h2 id="initial-setup">Initial setup</h2>
<p><strong>You do not need to clone the full repo as we distribute gancio via npm.</strong><br>
A Dockerfile and a docker-compose.yml are the only files needed.</p>
<ul>
<li>
<strong>Create a directory where everything related to gancio is stored (db, images, config)</strong>
<div class="language-bash highlighter-rouge">
<div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> /opt/gancio
<span class="nb">cd</span> /opt/gancio
</code></pre></div> </div>
<p><small>note that you can choose a different directory.</small></p>
</li>
</ul>
<h2 id="use-sqlite">Use sqlite</h2>
<div class="code-example bg-grey-lt-100">
<ol>
<li>
<strong>Download docker-compose.yml and Dockerfile</strong>
<div class="language-bash highlighter-rouge">
<div class="highlight"><pre class="highlight"><code>wget https://gancio.org/docker/Dockerfile
wget https://gancio.org/docker/sqlite/docker-compose.yml
</code></pre></div> </div>
</li>
<li>Create an empty db and config (<strong>this is needed</strong>)
<div class="highlighter-rouge">
<div class="highlight"><pre class="highlight"><code>touch config.json db.sqlite
mkdir user_locale
</code></pre></div> </div>
</li>
<li>Build docker image and launch interactive setup in one step
<div class="highlighter-rouge">
<div class="highlight"><pre class="highlight"><code>docker-compose build
docker-compose run --rm gancio gancio setup --docker --db=sqlite
</code></pre></div> </div>
</li>
</ol>
</div>
<h2 id="use-postgresql">Use postgreSQL</h2>
<div class="code-example bg-grey-lt-100">
<ol>
<li>
<strong>Download docker-compose.yml and Dockerfile</strong>
<div class="language-bash highlighter-rouge">
<div class="highlight"><pre class="highlight"><code>wget https://gancio.org/docker/Dockerfile
wget https://gancio.org/docker/postgres/docker-compose.yml
</code></pre></div> </div>
</li>
<li>Create an empty configuration (<strong>this is needed</strong>)
<div class="highlighter-rouge">
<div class="highlight"><pre class="highlight"><code>touch config.json
mkdir user_locale
</code></pre></div> </div>
</li>
<li>Build docker image and launch interactive setup in one step
<div class="highlighter-rouge">
<div class="highlight"><pre class="highlight"><code>docker-compose build
docker-compose run --rm gancio gancio setup --docker --db=postgres
</code></pre></div> </div>
</li>
</ol>
</div>
<h2 id="start-gancio">Start gancio</h2>
<ol>
<li>Run your container
<div class="language-bash highlighter-rouge">
<div class="highlight"><pre class="highlight"><code>docker-compose up <span class="nt">-d</span>
</code></pre></div> </div>
</li>
<li>Look at logs with
<div class="language-bash highlighter-rouge">
<div class="highlight"><pre class="highlight"><code>docker-compose logs
</code></pre></div> </div>
</li>
<li>
<p><a href="/install/nginx">Setup nginx as a proxy</a></p>
</li>
<li>
<p>Point your web browser to <a href="http://localhost:13120">http://localhost:13120</a> or where you specified during setup and enjoy <img class="emoji" title=":tada:" alt=":tada:" src="https://github.githubassets.com/images/icons/emoji/unicode/1f389.png" height="20" width="20"></p>
</li>
<li>You can edit <code class="highlighter-rouge">config.json</code> file and restart the container on your needs, see <a href="/config">Configuration</a> for more details.</li>
</ol>
<h2 id="upgrade">Upgrade</h2>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> /opt/gancio
docker-compose up <span class="nt">-d</span> <span class="nt">--no-deps</span> <span class="nt">--build</span>
</code></pre></div></div>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,383 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Nginx - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Nginx | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Nginx" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/install/nginx" />
<meta property="og:url" content="https://gancio.org/install/nginx" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/install/nginx","headline":"Nginx","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/install/nginx" class="navigation-list-link active">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/instances" class="navigation-list-link">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<nav class="breadcrumb-nav">
<ol class="breadcrumb-nav-list">
<li class="breadcrumb-nav-list-item"><a href="https://gancio.org/install">Install</a></li>
<li class="breadcrumb-nav-list-item"><span>Nginx</span></li>
</ol>
</nav>
<div id="main-content" class="page-content" role="main">
<h2 id="nginx-proxy-configuration">Nginx proxy configuration</h2>
<p>This is the default nginx configuration for gancio, please modify at least the <strong>server_name</strong> and <strong>ssl_certificate</strong>s path.<br />
Note that this does not include a cache configuration and that gancio does
not use a cache control at all, if you can help with this task youre
welcome.</p>
<div class="language-nginx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">server</span> <span class="p">{</span>
<span class="kn">listen</span> <span class="mi">80</span><span class="p">;</span>
<span class="kn">listen</span> <span class="s">[::]:80</span><span class="p">;</span>
<span class="kn">server_name</span> <span class="s">gancio.cisti.org</span><span class="p">;</span>
<span class="kn">root</span> <span class="n">/var/www/letsencrypt</span><span class="p">;</span>
<span class="kn">location</span> <span class="n">/.well-known/acme-challenge/</span> <span class="p">{</span> <span class="kn">allow</span> <span class="s">all</span><span class="p">;</span> <span class="p">}</span>
<span class="kn">location</span> <span class="n">/</span> <span class="p">{</span> <span class="kn">return</span> <span class="mi">301</span> <span class="s">https://</span><span class="nv">$host$request_uri</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
<span class="k">server</span> <span class="p">{</span>
<span class="kn">listen</span> <span class="mi">443</span> <span class="s">ssl</span> <span class="s">http2</span><span class="p">;</span>
<span class="kn">listen</span> <span class="s">[::]:443</span> <span class="s">ssl</span> <span class="s">http2</span><span class="p">;</span>
<span class="kn">server_name</span> <span class="s">gancio.cisti.org</span><span class="p">;</span>
<span class="kn">ssl_protocols</span> <span class="s">TLSv1.2</span><span class="p">;</span>
<span class="kn">ssl_ciphers</span> <span class="s">HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA</span><span class="p">;</span>
<span class="kn">ssl_prefer_server_ciphers</span> <span class="no">on</span><span class="p">;</span>
<span class="kn">ssl_session_cache</span> <span class="s">shared:SSL:10m</span><span class="p">;</span>
<span class="c1"># Uncomment these lines once you acquire a certificate:
</span> <span class="c1"># ssl_certificate /etc/letsencrypt/live/gancio.cisti.org/fullchain.pem;
</span> <span class="c1"># ssl_certificate_key /etc/letsencrypt/live/gancio.cisti.org/privkey.pem;
</span>
<span class="kn">keepalive_timeout</span> <span class="mi">70</span><span class="p">;</span>
<span class="kn">sendfile</span> <span class="no">on</span><span class="p">;</span>
<span class="kn">client_max_body_size</span> <span class="mi">80m</span><span class="p">;</span>
<span class="kn">gzip</span> <span class="no">on</span><span class="p">;</span>
<span class="kn">gzip_disable</span> <span class="s">"msie6"</span><span class="p">;</span>
<span class="kn">gzip_vary</span> <span class="no">on</span><span class="p">;</span>
<span class="kn">gzip_proxied</span> <span class="s">any</span><span class="p">;</span>
<span class="kn">gzip_comp_level</span> <span class="mi">6</span><span class="p">;</span>
<span class="kn">gzip_buffers</span> <span class="mi">16</span> <span class="mi">8k</span><span class="p">;</span>
<span class="kn">gzip_http_version</span> <span class="mi">1</span><span class="s">.1</span><span class="p">;</span>
<span class="kn">gzip_types</span> <span class="nc">text/plain</span> <span class="nc">text/css</span> <span class="nc">application/json</span> <span class="nc">application/javascript</span> <span class="nc">text/xml</span> <span class="nc">application/xml</span> <span class="nc">application/xml</span><span class="s">+rss</span> <span class="nc">text/javascript</span><span class="p">;</span>
<span class="kn">add_header</span> <span class="s">Strict-Transport-Security</span> <span class="s">"max-age=31536000"</span><span class="p">;</span>
<span class="kn">location</span> <span class="n">/</span> <span class="p">{</span>
<span class="kn">try_files</span> <span class="nv">$uri</span> <span class="s">@proxy</span><span class="p">;</span>
<span class="p">}</span>
<span class="kn">location</span> <span class="s">@proxy</span> <span class="p">{</span>
<span class="kn">proxy_set_header</span> <span class="s">Host</span> <span class="nv">$host</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-Proto</span> <span class="s">https</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">Proxy</span> <span class="s">""</span><span class="p">;</span>
<span class="kn">proxy_pass_header</span> <span class="s">Server</span><span class="p">;</span>
<span class="kn">proxy_pass</span> <span class="s">http://127.0.0.1:13120</span><span class="p">;</span>
<span class="kn">proxy_buffering</span> <span class="no">on</span><span class="p">;</span>
<span class="kn">proxy_redirect</span> <span class="no">off</span><span class="p">;</span>
<span class="kn">proxy_http_version</span> <span class="mi">1</span><span class="s">.1</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">Upgrade</span> <span class="nv">$http_upgrade</span><span class="p">;</span>
<span class="kn">proxy_set_header</span> <span class="s">Connection</span> <span class="nv">$connection_upgrade</span><span class="p">;</span>
<span class="kn">tcp_nodelay</span> <span class="no">on</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,314 +0,0 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Instances - Gancio</title>
<link rel="shortcut icon" href="https://gancio.org/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://gancio.org/assets/css/just-the-docs.css">
<link rel="stylesheet" href="https://gancio.org/assets/css/style.css">
<script type="text/javascript" src="https://gancio.org/assets/js/vendor/lunr.min.js"></script>
<script type="text/javascript" src="https://gancio.org/assets/js/just-the-docs.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://gancio.org/assets/js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="https://gancio.org/assets/css/jquery.fancybox.min.css"/>
<script src="https://gancio.org/assets/js/jquery.fancybox.min.js"></script>
<!-- Begin Jekyll SEO tag v2.6.1 -->
<title>Instances | Gancio</title>
<meta name="generator" content="Jekyll v3.8.6" />
<meta property="og:title" content="Instances" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="A shared agenda for local communities with AP support" />
<meta property="og:description" content="A shared agenda for local communities with AP support" />
<link rel="canonical" href="https://gancio.org/instances" />
<meta property="og:url" content="https://gancio.org/instances" />
<meta property="og:site_name" content="Gancio" />
<script type="application/ld+json">
{"@type":"WebPage","url":"https://gancio.org/instances","headline":"Instances","description":"A shared agenda for local communities with AP support","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->
</head>
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="https://gancio.org/" class="site-title fs-6 lh-tight">Gancio</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
<li class="navigation-list-item active">
<a href="https://gancio.org/404.html" class="navigation-list-link"></a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/" class="navigation-list-link">Home</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/install" class="navigation-list-link">Install</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/install/debian" class="navigation-list-link">Debian</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/docker" class="navigation-list-link">Docker</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/install/nginx" class="navigation-list-link">Nginx</a>
</li>
</ul>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/config" class="navigation-list-link">Configuration</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/dev" class="navigation-list-link">Hacking</a>
<ul class="navigation-list-child-list ">
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/locales" class="navigation-list-link">Support a new language</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/migration" class="navigation-list-link">Migration</a>
</li>
<li class="navigation-list-item ">
<a href="https://gancio.org/dev/structure" class="navigation-list-link">Project Structure</a>
</li>
</ul>
</li>
<li class="navigation-list-item active">
<a href="https://gancio.org/instances" class="navigation-list-link active">Instances</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/about" class="navigation-list-link">About</a>
</li>
<li class="navigation-list-item">
<a href="https://gancio.org/federation" class="navigation-list-link">Federation</a>
</li>
</ul>
</nav>
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search Gancio" aria-label="Search Gancio" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li class="d-inline-block my-0 mr-2"><a href="https://blog.gancio.org">Blog</a></li>
<li class="d-inline-block my-0 mr-2"><a href="https://framagit.org/les/gancio">Source</a></li>
<li class="d-inline-block my-0"><a href="https://socialhub.activitypub.rocks/c/software/gancio">Forum</a></li>
</ul>
</div>
</div>
<div class="main-content">
<div id="main-content" class="page-content" role="main">
<h2 id="instances">Instances</h2>
<ul>
<li><a href="https://gancio.cisti.org">gancio.cisti.org</a> (Torino, Italy)</li>
<li><a href="https://lapunta.org">lapunta.org</a> (Firenze, Italy)</li>
</ul>
</div>
</div>
</div>
</div>
</body>
</html>

4
docs/assets/css/fa.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,90 @@
.premonition {
display: grid;
grid-template-columns: 43px auto;
padding-top: 13px;
padding-bottom: 6px;
margin: 30px 0 30px 0;
background-color: #e3edf2;
border-left: 4px solid #5bc0de;
color: #5bc0de;
}
.premonition code {
background-color: #fff;
color: #5bc0de;
}
.premonition .header {
font-weight: 700;
font-size: 15px;
color: #5bc0de;
}
.premonition .fa {
font-size: 18px;
opacity: .3;
padding-top: 2px;
padding-left: 20px;
}
.premonition .content {
color: rgba(0, 0, 0, 0.5);
padding-right: 40px;
}
.premonition.info {
background-color: #f3f8f3;
color: #50af51;
border-color: #50af51;
}
.premonition.info a {
color: #50af51;
text-decoration: underline;
}
.premonition.info code {
color: #50af51;
}
.premonition.info .header {
color: #50af51;
}
.premonition.warning {
background-color: #fcf8f2;
color: #f0ad4e;
border-color: #f0ad4e;
}
.premonition.warning a {
color: #f0ad4e;
text-decoration: underline;
}
.premonition.warning code {
color: #f0ad4e;
}
.premonition.warning .header {
color: #f0ad4e;
}
.premonition.error {
background-color: #fdf7f7;
color: #d9534f;
border-color: #d9534f;
}
.premonition.error a {
color: #d9534f;
text-decoration: underline;
}
.premonition.error code {
color: #d9534f;
}
.premonition.error .header {
color: #d9534f;
}

View file

@ -1,12 +1,16 @@
.navigation-list-item {
/* .navigation-list-item {
font-size: 18px !important;
padding: 4px;
}
.navigation-list-item a {
color: blue;
html, body {
font-family: sans-serif;
}
.navigation-list-item a:hover {
color: black;
.page-content h1:first-of-type {
font-weight: 500;
}
li {
margin-left: 10px;
} */

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
docs/assets/gancio.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
docs/assets/oauth_auth.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

180
docs/changelog.md Normal file
View file

@ -0,0 +1,180 @@
---
layout: default
title: Changelog
permalink: /changelog
nav_order: 10
---
All notable changes to this project will be documented in this file.
### 0.24.0
- New Euskara language from Basque Country, thanks @hacklabkelo
- fix feed with filters
- cleaner homepage
- fix next/prev recurrent events
- fix some history navigation issue
- fix blank lines in description
- upgrade deps
- better custom logo management
- fix settings update
### 0.23.0
- send AP Event Object instead of Note
- show only future unconfirmed events in admin panel
- new polish locale
- add friendly instances (an additional menu is shown)
- use user's logo not project's logo in federation
- start WPGancio plugin
- support media upload via url (API only)
- confirm before remove a resource
- confirm before remove a friendly instance
- event description supports some html tag
- fix redirect after login
### 0.22.0
- add admin announcement support (fix #74)
- each instance has a specific timezone you can choose from admin's panel
- refactoring language management (you can choose a default instance's language):
usually UX language is choosen looking at Accepted-Language header but there
are messages not generated from an http request (eg. sending events via AP).
In those cases a default instance's language is choosen (default 'en').
- use lazy loaded images
- better mobile experience for admins
- single day only recurring events
- fix user block in fediverse moderation
- filter and linkify content from fediverse
- add a lot of help strings in admin panel
- use html2text for event description in og: meta
- update deps
- fix a moment.js typo from/to issue
- fix #73
### 0.21.0
- a new recurring events logic (a la taskwarrior):
- each occurrence of a recurring event could be personalized.
- occurrence of recurring events are skippable.
- occurrence generation could be paused.
- support `h-event` microformats! in homepage and in any single event's page
- add a background task manager (email, recurring events creation)
- sanitize html content coming from fediverse and event description with dompurify
- also remove `fbclid` params in links
- front end search optimization
- use oauth2 for everything, password flow for webclient, this also fix
some issue with authentication
- clickable tags / places @ home (to add them as filters)
- use a cleaner menububble for the new editor
- add local smtp and sendmail options on configuration setup
- check permission for resource removal request from fediverse
- add resource from fediverse also when inReplyTo is another resource
- automatic API documentation inclusion in docs
- split moderation in another tab inside admin panel
- use axios instead of fetch everywhere
- lot of ux improvements & error handling
- search links in event description with linkifyjs while add/edit events
- remove text templates for emails and use html2text instead
- fix email unique index for users!
### 0.20.0
- New layout (navbar/footer/visible filters)
- two month calendar on large display
- admin could edit title, description, about, favicon & logo directly form admin panel
- new add event layout => https://demo.gancio.org/add
- new editor to describe events (bold, italic, link) supported also using copy/paste
- the editor also support live markdown (try using ### at line start)
- start oauth2 server implementation (documentation: https://gancio.org/dev/oauth)
- add fediverse moderation
- fix embedding an event via iframe
- images converted in .webp
- new catalan translation, thanks @fadelkon
### 0.17.14
- [locale] add catalan
- [fix] fedi outbox
### 0.17.12
- [ui] add admin section on event page in mobile #63
- [fix] remove username from users
### 0.17.11
- [refactor] s/fed_user/ap_user
- [fedi] admin moderation
### 0.17.10
- [refactor] s/comment/resource/
- [refactor] remove `username` field
- [doc] about and federation
### 0.17.8
- [fix] use thumb in head og:img only
### 0.17.7
- [fix] #58 wrong url for RSS feed
### 0.17.5
- [fedi] comments moderation
- [fedi] user moderation
- [fedi] instance moderation
- [hotfix] cli setup
- [doc] fix debian upgrade
- [fix] comment ap_id key length
- [fix] fediverse signature
- [fedi] better /inbox /followers response
### 0.17.0
- [feat] add rss link @homepage
- [ui] add lot of explanation text
- [ui] show copied messages
- [admin] show n of unconfirmed users/events
- [ui] spinner while event image is loading
- [fedi] add follow me dialog in event
- [fix] do not add reminders in full ics export
- [fix] remove spaces from hashtags sent via AP
- [fix] #56 unconfirmed event sent via ap
- [fix] localPosts/comments in fediverse stats
### 0.16.0
- [feat] embed event as widget in external website
- [fedi] instances moderation in admin
- [fix] toggle event visibility by owner
- [fedi] manage unboost
- [refactoring] auth as middleware
### 0.15.7
- [fix] minor
### 0.15.6
- [fix] tags in event
### 0.15.5
- [model] migrations setup
- [feat] embeddable event widget/iframe
### 0.15.2
- [fix] delete event
- [fix] wrong html hierarchy
### 0.15.0
- [fix] backtop icon on mobile
- [fix] webfinger nodeinfo return real node info
- [fix] register email confirmation
- [feat] add federation settings (enable comments/boost/like)
- [feat] new event page layout
- [feat] could download .ics of event
- [feat] add cors to feed requests
- [refactoring] settings middleware, cleaning codebase
### 0.14.18
- [improve] better quality for images
- [fix] password recovery email
- [feat] new action field for notification
- [feat] add DEBUG env variable in docker-compose.yml
- [style] fixed width in confirmation events table
- [fix] #38 timezone issue in rss export and using tor...
### 0.14.17
- [fix] image previews from external website
- [fix] docker-compose postgresql docs
- [improve] export white logo to fediverse

11
docs/contact.md Normal file
View file

@ -0,0 +1,11 @@
---
layout: default
title: Contacts
permalink: /contacts
nav_order: 9
---
## Contacts
### :elephant: Mastodon ⇒ [@gancio@mastodon.cisti.org](https://mastodon.cisti.org/@gancio)

71
docs/dev/api.md Normal file
View file

@ -0,0 +1,71 @@
---
layout: default
title: API
permalink: /dev/api
parent: Hacking
nav_order: 8
---
1. TOC
{:toc}
## Add a new event
POST
{: .label .label-orange}
**`/event`**
> info "info"
> `Content-Type` has to be `multipart/form-data` 'cause support image upload
**Params**
| title | `string` | event's title |
| description | `string` | event's description (html accepted and sanitized) |
| place_name | `string` | the name of the place |
| place_address | `string` | the address of the place |
| start_datetime | `integer` | start timestamp |
| multidate | `integer` | is a multidate event? |
| tags | `array` | List of tags |
| recurrent | `object` | Recurrent event details |
| recurrent.frequency | `string` | could be `1w` or `2w` |
| recurrent.type | `string` | not used |
| recurrent.days | `array` | array of days |
| image | `image` | Image |
---
## Get current authenticated user
GET
{: .label .label-green}
**`/api/user`**
**Response**
```json
{
"description" : null,
"recover_code" : "",
"id" : 1,
"createdAt" : "2020-01-29T18:10:16.630Z",
"updatedAt" : "2020-01-30T22:42:14.789Z",
"is_active" : true,
"settings" : "{}",
"email" : "eventi@cisti.org",
"is_admin" : true
}
```
---

Some files were not shown because too many files have changed in this diff Show more