Add new description field to lists. Closes #925.

This commit is contained in:
Kailash Nadh 2022-11-01 20:59:21 +05:30
parent 95b8df2918
commit ef1f84ee7c
32 changed files with 76 additions and 6 deletions

View file

@ -74,6 +74,7 @@ func install(lastVer string, db *sqlx.DB, fs stuffbin.FileSystem, prompt, idempo
models.ListTypePrivate,
models.ListOptinSingle,
pq.StringArray{"test"},
"",
); err != nil {
lo.Fatalf("error creating list: %v", err)
}
@ -83,6 +84,7 @@ func install(lastVer string, db *sqlx.DB, fs stuffbin.FileSystem, prompt, idempo
models.ListTypePublic,
models.ListOptinDouble,
pq.StringArray{"test"},
"",
); err != nil {
lo.Fatalf("error creating list: %v", err)
}

View file

@ -51,6 +51,7 @@ describe('Lists', () => {
cy.get('select[name=type]').select('public');
cy.get('select[name=optin]').select('double');
cy.get('input[name=tags]').clear().type(`tag${n}{enter}`);
cy.get('textarea[name=description]').clear().type(`desc${n}`);
cy.get('[data-cy=btn-save]').click();
cy.wait(100);
});
@ -94,6 +95,7 @@ describe('Lists', () => {
cy.get('select[name=type]').select(t);
cy.get('select[name=optin]').select(o);
cy.get('input[name=tags]').type(`tag${n}{enter}${t}{enter}${o}{enter}`);
cy.get('textarea[name=description]').clear().type(`desc-${t}-${n}`);
cy.get('[data-cy=btn-save]').click();
cy.wait(200);
@ -133,4 +135,22 @@ describe('Lists', () => {
cy.sortTable('thead th.cy-updated_at', [3, 4, 5, 6]);
cy.sortTable('thead th.cy-updated_at', [6, 5, 4, 3]);
});
it('Opens forms page', () => {
const apiUrl = Cypress.env('apiUrl');
cy.loginAndVisit(`${apiUrl}/subscription/form`);
cy.get('ul li').its('length').should('eq', 2);
const cases = [
{ 'name': 'list-public-single-2', 'description': 'desc-public-2' },
{ 'name': 'list-public-double-3', 'description': 'desc-public-3' }
];
cases.forEach((c, n) => {
cy.get('ul li').eq(n).then(($el) => {
cy.wrap($el).get('label').contains(c.name);
cy.wrap($el).get('.description').contains(c.description);
});
});
});
});

View file

@ -47,7 +47,7 @@
<template v-for="l in publicLists"><span v-if="l.uuid in selected" :key="l.id" :set="id = l.uuid.substr(0, 5)">
&lt;p&gt;
&lt;input id=&quot;{{ id }}&quot; type=&quot;checkbox&quot; name=&quot;l&quot; checked value=&quot;{{ l.uuid }}&quot; /&gt;
&lt;label for=&quot;{{ id }}&quot;&gt;{{ l.name }}&lt;/label&gt;
&lt;label for=&quot;{{ id }}&quot;&gt;{{ l.name }}&lt;/label&gt;<template v-if="l.description">&lt;br /&gt;&lt;span&gt;{{ l.description }}&lt;/span&gt;</template>
&lt;/p&gt;</span></template>
&lt;p&gt;&lt;input type=&quot;submit&quot; value=&quot;{{ $t('public.sub') }}&quot; /&gt;&lt;/p&gt;

View file

@ -38,6 +38,11 @@
<b-taginput v-model="form.tags" name="tags" ellipsis
icon="tag-outline" :placeholder="$t('globals.terms.tags')"></b-taginput>
</b-field>
<b-field :label="$t('globals.fields.description')" label-position="on-border">
<b-input :maxlength="2000" v-model="form.description" name="description" type="textarea"
:placeholder="$t('globals.fields.description')"></b-input>
</b-field>
</section>
<footer class="modal-card-foot has-text-right">
<b-button @click="$parent.close()">{{ $t('globals.buttons.close') }}</b-button>

View file

@ -143,6 +143,7 @@
"globals.days.6": "dv.",
"globals.days.7": "ds.",
"globals.fields.createdAt": "Creat",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Nom",
"globals.fields.status": "Estat",

View file

@ -144,6 +144,7 @@
"globals.days.6": "So",
"globals.days.7": "Sat",
"globals.fields.createdAt": "Vytvořeno",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Jméno",
"globals.fields.status": "Stav",

View file

@ -144,6 +144,7 @@
"globals.days.6": "Sa",
"globals.days.7": "Sat",
"globals.fields.createdAt": "Erstellt",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Name",
"globals.fields.status": "Status",

View file

@ -143,6 +143,7 @@
"globals.days.6": "Fri",
"globals.days.7": "Sat",
"globals.fields.createdAt": "Created",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Name",
"globals.fields.status": "Status",

View file

@ -144,6 +144,7 @@
"globals.days.6": "Vie",
"globals.days.7": "Sáb",
"globals.fields.createdAt": "Creado",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Nombre",
"globals.fields.status": "Estado",

View file

@ -144,6 +144,7 @@
"globals.days.6": "Fri",
"globals.days.7": "Sat",
"globals.fields.createdAt": "Created",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Nimi",
"globals.fields.status": "Tila",

View file

@ -144,6 +144,7 @@
"globals.days.6": "sam.",
"globals.days.7": "Dim",
"globals.fields.createdAt": "Créé·e le",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Nom",
"globals.fields.status": "Statut",

View file

@ -144,6 +144,7 @@
"globals.days.6": "Szombat",
"globals.days.7": "Sat",
"globals.fields.createdAt": "Létrehozva",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Név",
"globals.fields.status": "Státusz",

View file

@ -144,6 +144,7 @@
"globals.days.6": "sab",
"globals.days.7": "Sat",
"globals.fields.createdAt": "Creato il ",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Nome",
"globals.fields.status": "Stato",

View file

@ -144,6 +144,7 @@
"globals.days.6": "金",
"globals.days.7": "土",
"globals.fields.createdAt": "作成済み",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "名前",
"globals.fields.status": "ステータス",

View file

@ -144,6 +144,7 @@
"globals.days.6": "ശനി",
"globals.days.7": "Sat",
"globals.fields.createdAt": "നിർമ്മിച്ചത്",
"globals.fields.description": "Description",
"globals.fields.id": "ഐഡി",
"globals.fields.name": "പേര്",
"globals.fields.status": "സ്ഥിതി",

View file

@ -144,6 +144,7 @@
"globals.days.6": "Za",
"globals.days.7": "Zat",
"globals.fields.createdAt": "Aangemaakt",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Naam",
"globals.fields.status": "Status",

View file

@ -144,6 +144,7 @@
"globals.days.6": "Sob",
"globals.days.7": "Sat",
"globals.fields.createdAt": "Utworzone",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Nazwa",
"globals.fields.status": "Status",

View file

@ -144,6 +144,7 @@
"globals.days.6": "Sex",
"globals.days.7": "Sáb",
"globals.fields.createdAt": "Criado",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Nome",
"globals.fields.status": "Status",

View file

@ -144,6 +144,7 @@
"globals.days.6": "Sáb",
"globals.days.7": "Sat",
"globals.fields.createdAt": "Criado a",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Nome",
"globals.fields.status": "Estado",

View file

@ -144,6 +144,7 @@
"globals.days.6": "Sa",
"globals.days.7": "Sat",
"globals.fields.createdAt": "Creat",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Nume",
"globals.fields.status": "Stare",

View file

@ -144,6 +144,7 @@
"globals.days.6": "Сб",
"globals.days.7": "Sat",
"globals.fields.createdAt": "Создано",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Имя",
"globals.fields.status": "Статус",

View file

@ -144,6 +144,7 @@
"globals.days.6": "Cts",
"globals.days.7": "Sat",
"globals.fields.createdAt": "Yaratılma",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "İsim",
"globals.fields.status": "Durum",

View file

@ -144,6 +144,7 @@
"globals.days.6": "Thứ 7",
"globals.days.7": "Sat",
"globals.fields.createdAt": "Đã tạo",
"globals.fields.description": "Description",
"globals.fields.id": "ID",
"globals.fields.name": "Tên",
"globals.fields.status": "Trạng thái",

View file

@ -144,6 +144,7 @@
"globals.days.6": "星期五",
"globals.days.7": "星期六",
"globals.fields.createdAt": "已创建",
"globals.fields.description": "Description",
"globals.fields.id": "身份标识",
"globals.fields.name": "姓名",
"globals.fields.status": "状态",

View file

@ -144,6 +144,7 @@
"globals.days.6": "星期五",
"globals.days.7": "星期六",
"globals.fields.createdAt": "已創建",
"globals.fields.description": "Description",
"globals.fields.id": "身份標識",
"globals.fields.name": "姓名",
"globals.fields.status": "狀態",

View file

@ -120,7 +120,7 @@ func (c *Core) CreateList(l models.List) (models.List, error) {
// Insert and read ID.
var newID int
l.UUID = uu.String()
if err := c.q.CreateList.Get(&newID, l.UUID, l.Name, l.Type, l.Optin, pq.StringArray(normalizeTags(l.Tags))); err != nil {
if err := c.q.CreateList.Get(&newID, l.UUID, l.Name, l.Type, l.Optin, pq.StringArray(normalizeTags(l.Tags)), l.Description); err != nil {
c.log.Printf("error creating list: %v", err)
return models.List{}, echo.NewHTTPError(http.StatusInternalServerError,
c.i18n.Ts("globals.messages.errorCreating", "name", "{globals.terms.list}", "error", pqErrMsg(err)))
@ -131,7 +131,7 @@ func (c *Core) CreateList(l models.List) (models.List, error) {
// UpdateList updates a given list.
func (c *Core) UpdateList(id int, l models.List) (models.List, error) {
res, err := c.q.UpdateList.Exec(id, l.Name, l.Type, l.Optin, pq.StringArray(normalizeTags(l.Tags)))
res, err := c.q.UpdateList.Exec(id, l.Name, l.Type, l.Optin, pq.StringArray(normalizeTags(l.Tags)), l.Description)
if err != nil {
c.log.Printf("error updating list: %v", err)
return models.List{}, echo.NewHTTPError(http.StatusInternalServerError,

View file

@ -12,7 +12,12 @@ func V2_3_0(db *sqlx.DB, fs stuffbin.FileSystem, ko *koanf.Koanf) error {
return err
}
// Insert appearance related settings.
// Add `description` field to lists.
if _, err := db.Exec(`ALTER TABLE lists ADD COLUMN IF NOT EXISTS "description" TEXT NOT NULL DEFAULT ''`); err != nil {
return err
}
// Insert new preference settings.
if _, err := db.Exec(`
INSERT INTO settings (key, value) VALUES
('privacy.allow_preferences', 'false')

View file

@ -214,6 +214,7 @@ type List struct {
Type string `db:"type" json:"type"`
Optin string `db:"optin" json:"optin"`
Tags pq.StringArray `db:"tags" json:"tags"`
Description string `db:"description" json:"description"`
SubscriberCount int `db:"-" json:"subscriber_count"`
SubscriberCounts StringIntMap `db:"subscriber_statuses" json:"subscriber_statuses"`
SubscriberID int `db:"subscriber_id" json:"-"`

View file

@ -418,7 +418,7 @@ SELECT * FROM lists WHERE (CASE WHEN $1 != '' THEN optin=$1::list_optin ELSE TRU
END) ORDER BY name;
-- name: create-list
INSERT INTO lists (uuid, name, type, optin, tags) VALUES($1, $2, $3, $4, $5) RETURNING id;
INSERT INTO lists (uuid, name, type, optin, tags, description) VALUES($1, $2, $3, $4, $5, $6) RETURNING id;
-- name: update-list
UPDATE lists SET
@ -426,6 +426,7 @@ UPDATE lists SET
type=(CASE WHEN $3 != '' THEN $3::list_type ELSE type END),
optin=(CASE WHEN $4 != '' THEN $4::list_optin ELSE optin END),
tags=$5::VARCHAR(100)[],
description=(CASE WHEN $6 != '' THEN $6 ELSE description END),
updated_at=NOW()
WHERE id = $1;

View file

@ -33,6 +33,7 @@ CREATE TABLE lists (
type list_type NOT NULL,
optin list_optin NOT NULL DEFAULT 'single',
tags VARCHAR(100)[],
description TEXT NOT NULL DEFAULT '',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()

View file

@ -21,7 +21,7 @@ a:hover {
}
label {
cursor: pointer;
color: #666;
color: #444;
}
h1,
h2,
@ -118,7 +118,18 @@ input[disabled] {
.lists {
list-style-type: none;
padding: 0;
margin-bottom: 30px;
}
.lists li {
margin: 0 0 5px 0;
}
.lists .description {
margin: 0 0 15px 0;
font-size: 0.875em;
line-height: 1.3rem;
color: #888;
margin-left: 25px;
}
.form .nonce {
display: none;
}

View file

@ -22,6 +22,9 @@
<li>
<input checked="true" id="l-{{ $l.UUID}}" type="checkbox" name="l" value="{{ $l.UUID }}" >
<label for="l-{{ $l.UUID}}">{{ $l.Name }}</label>
{{ if ne $l.Description "" }}
<p class="description">{{ $l.Description }}</p>
{{ end }}
</li>
{{ end }}
</ul>