Add live preview of project card stuff
This commit is contained in:
parent
51ad8d03d4
commit
22c70cda8e
|
@ -1,4 +1,7 @@
|
||||||
function ImageSelector(form, maxFileSize, container, defaultImageUrl) {
|
function ImageSelector(form, maxFileSize, container, {
|
||||||
|
defaultImageUrl = "",
|
||||||
|
onUpdate = (url) => {},
|
||||||
|
} = {}) {
|
||||||
this.form = form;
|
this.form = form;
|
||||||
this.maxFileSize = maxFileSize;
|
this.maxFileSize = maxFileSize;
|
||||||
this.fileInput = container.querySelector(".imginput");
|
this.fileInput = container.querySelector(".imginput");
|
||||||
|
@ -11,12 +14,13 @@ function ImageSelector(form, maxFileSize, container, defaultImageUrl) {
|
||||||
this.originalImageUrl = this.imageEl.getAttribute("data-imginput-original");
|
this.originalImageUrl = this.imageEl.getAttribute("data-imginput-original");
|
||||||
this.originalImageFilename = this.imageEl.getAttribute("data-imginput-original-filename");
|
this.originalImageFilename = this.imageEl.getAttribute("data-imginput-original-filename");
|
||||||
this.currentImageUrl = this.originalImageUrl;
|
this.currentImageUrl = this.originalImageUrl;
|
||||||
this.defaultImageUrl = defaultImageUrl || "";
|
this.defaultImageUrl = defaultImageUrl;
|
||||||
|
this.onUpdate = onUpdate;
|
||||||
|
|
||||||
this.fileInput.value = "";
|
this.fileInput.value = "";
|
||||||
this.removeImageInput.value = "";
|
this.removeImageInput.value = "";
|
||||||
|
|
||||||
this.setImageUrl(this.originalImageUrl);
|
this.setImageUrl(this.originalImageUrl, true);
|
||||||
this.updatePreview();
|
this.updatePreview();
|
||||||
|
|
||||||
this.fileInput.addEventListener("change", function(ev) {
|
this.fileInput.addEventListener("change", function(ev) {
|
||||||
|
@ -79,7 +83,7 @@ ImageSelector.prototype.setError = function(error) {
|
||||||
this.fileInput.reportValidity();
|
this.fileInput.reportValidity();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageSelector.prototype.setImageUrl = function(url) {
|
ImageSelector.prototype.setImageUrl = function(url, initial = false) {
|
||||||
this.currentImageUrl = url;
|
this.currentImageUrl = url;
|
||||||
this.imageEl.src = url;
|
this.imageEl.src = url;
|
||||||
if (url.length > 0) {
|
if (url.length > 0) {
|
||||||
|
@ -87,6 +91,10 @@ ImageSelector.prototype.setImageUrl = function(url) {
|
||||||
} else {
|
} else {
|
||||||
this.imageEl.style.display = "none";
|
this.imageEl.style.display = "none";
|
||||||
}
|
}
|
||||||
|
this.url = url;
|
||||||
|
if (!initial) {
|
||||||
|
this.onUpdate(url);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageSelector.prototype.updatePreview = function(file) {
|
ImageSelector.prototype.updatePreview = function(file) {
|
||||||
|
|
|
@ -8501,6 +8501,17 @@ span.icon-rss::before {
|
||||||
content: "\200b";
|
content: "\200b";
|
||||||
padding: var(--spacing-2) 0;
|
padding: var(--spacing-2) 0;
|
||||||
}
|
}
|
||||||
|
.project-homepage-card {
|
||||||
|
width: 100%;
|
||||||
|
max-width: var(--site-width-narrow);
|
||||||
|
padding: var(--spacing-3);
|
||||||
|
background-color: var(--c-transparent-background);
|
||||||
|
--link-color: var(--color);
|
||||||
|
display: flex;
|
||||||
|
gap: var(--spacing-3);
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: -4rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* src/rawdata/scss/showcase.css */
|
/* src/rawdata/scss/showcase.css */
|
||||||
.showcase-item .gradient {
|
.showcase-item .gradient {
|
||||||
|
|
|
@ -94,4 +94,17 @@
|
||||||
content: '\200b';
|
content: '\200b';
|
||||||
padding: var(--spacing-2) 0;
|
padding: var(--spacing-2) 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-homepage-card {
|
||||||
|
width: 100%;
|
||||||
|
max-width: var(--site-width-narrow);
|
||||||
|
padding: var(--spacing-3);
|
||||||
|
background-color: var(--c-transparent-background);
|
||||||
|
--link-color: var(--color);
|
||||||
|
display: flex;
|
||||||
|
gap: var(--spacing-3);
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
margin-top: -4rem;
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@
|
||||||
{{ $filename := or (and .Asset .Asset.Filename) "" }}
|
{{ $filename := or (and .Asset .Asset.Filename) "" }}
|
||||||
<img class="w4 flex-shrink-0" data-imginput-original="{{ $url }}" data-imginput-original-filename="{{ $filename }}" src="{{ $url }}" />
|
<img class="w4 flex-shrink-0" data-imginput-original="{{ $url }}" data-imginput-original-filename="{{ $filename }}" src="{{ $url }}" />
|
||||||
<div class="w1 flex-grow-1 flex flex-column g1">
|
<div class="w1 flex-grow-1 flex flex-column g1">
|
||||||
<div class="flex f6">
|
<div class="flex f6 g2">
|
||||||
<a href="javascript:;" class="imginput-reset-link">Reset</a>
|
<a href="javascript:;" class="imginput-reset-link">Reset</a>
|
||||||
<a href="javascript:;" class="imginput-remove-link">Remove</a>
|
<a href="javascript:;" class="imginput-remove-link">Remove</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -157,26 +157,22 @@
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<div class="pv4 f6 tc">You are not following anything. Follow users and projects to see their posts here.</div>
|
<div class="pv4 f6 tc">You are not following anything. Follow users and projects to see their posts here.</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
TODO: READ MORE LINK
|
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
<div data-tab="featured" class="timeline">
|
<div data-tab="featured" class="timeline">
|
||||||
{{ range .FeaturedItems }}
|
{{ range .FeaturedItems }}
|
||||||
{{ template "timeline_item.html" . }}
|
{{ template "timeline_item.html" . }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
TODO: READ MORE LINK
|
|
||||||
</div>
|
</div>
|
||||||
<div data-tab="recent" class="timeline">
|
<div data-tab="recent" class="timeline">
|
||||||
{{ range .RecentItems }}
|
{{ range .RecentItems }}
|
||||||
{{ template "timeline_item.html" . }}
|
{{ template "timeline_item.html" . }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
TODO: READ MORE LINK
|
|
||||||
</div>
|
</div>
|
||||||
<div data-tab="news" class="timeline">
|
<div data-tab="news" class="timeline">
|
||||||
{{ range .NewsItems }}
|
{{ range .NewsItems }}
|
||||||
{{ template "timeline_item.html" . }}
|
{{ template "timeline_item.html" . }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
TODO: READ MORE LINK
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -49,12 +49,24 @@
|
||||||
<div class="flex flex-column g3">
|
<div class="flex flex-column g3">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<label>Project Title*</label>
|
<label>Project Title*</label>
|
||||||
<input required type="text" name="project_name" maxlength="255" class="textbox" value="{{ .ProjectSettings.Name }}">
|
<input
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
id="project_name" name="project_name"
|
||||||
|
maxlength="255"
|
||||||
|
value="{{ .ProjectSettings.Name }}"
|
||||||
|
oninput="updateCardPreview()"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<label>Short Description*</label>
|
<label>Short Description*</label>
|
||||||
<textarea id="description" required maxlength="140" name="shortdesc">
|
<textarea
|
||||||
|
required
|
||||||
|
id="description" name="shortdesc"
|
||||||
|
maxlength="140"
|
||||||
|
oninput="updateCardPreview()"
|
||||||
|
>
|
||||||
{{- .ProjectSettings.Blurb -}}
|
{{- .ProjectSettings.Blurb -}}
|
||||||
</textarea>
|
</textarea>
|
||||||
<div class="f6">Plaintext only. No links or markdown.</div>
|
<div class="f6">Plaintext only. No links or markdown.</div>
|
||||||
|
@ -215,6 +227,13 @@
|
||||||
<!-- need href and title -->
|
<!-- need href and title -->
|
||||||
<a data-tmpl="root" class="ph2 flex"><!-- need icon --></a>
|
<a data-tmpl="root" class="ph2 flex"><!-- need icon --></a>
|
||||||
</template>
|
</template>
|
||||||
|
<template id="owner_preview">
|
||||||
|
<div class="flex g1 items-center b">
|
||||||
|
<img data-tmpl="avatar" class="avatar avatar-user avatar-small"><!-- need src -->
|
||||||
|
<span data-tmpl="name"><!-- need name --></span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<div hidden>
|
<div hidden>
|
||||||
{{ range .AllLogos }}
|
{{ range .AllLogos }}
|
||||||
<span id="link-icon-{{ .Name }}">{{ .Svg }}</span>
|
<span id="link-icon-{{ .Name }}">{{ .Svg }}</span>
|
||||||
|
@ -226,17 +245,43 @@
|
||||||
We don't have a good story for sharing templates between Go and JS.
|
We don't have a good story for sharing templates between Go and JS.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- Header image / links -->
|
<div class="flex flex-column items-center">
|
||||||
<div id="header_img_preview" class="project-header-img"><!-- Needs background-image -->
|
<!-- Header image / links -->
|
||||||
<div class="flex justify-end pa3">
|
<div id="header_img_preview" class="project-header-img"><!-- Needs background-image -->
|
||||||
<div class="flex g3">
|
<div class="flex justify-end pa3">
|
||||||
<div id="primary_links_preview" class="project-links hide-if-empty"></div>
|
<div class="flex g3">
|
||||||
<div id="secondary_links_preview" class="project-links ph1 hide-if-empty"></div>
|
<div id="primary_links_preview" class="project-links hide-if-empty"></div>
|
||||||
|
<div id="secondary_links_preview" class="project-links ph1 hide-if-empty"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Card -->
|
||||||
|
<div class="project-homepage-card">
|
||||||
|
<div id="logo_preview" class="flex-shrink-0 flex">
|
||||||
|
<img class="project-card-logo" alt="Project Logo">
|
||||||
|
</div>
|
||||||
|
<div class="details flex-grow-1">
|
||||||
|
<h3 id="name_preview" class="b mb2 f4"></h3>
|
||||||
|
<div id="blurb_preview" class="blurb"></div>
|
||||||
|
<div id="owners_preview_container">
|
||||||
|
<hr class="mv3">
|
||||||
|
<div id="owners_preview" class="flex flex-wrap g2">
|
||||||
|
<!-- TODO(redesign): Actually preview owners -->
|
||||||
|
<div class="flex g1 items-center b">
|
||||||
|
<div class="avatar avatar-user avatar-small"></div>
|
||||||
|
<span>Example User</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- TODO(redesign): Preview badges -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Long description preview -->
|
<!-- Long description preview -->
|
||||||
|
<h3 class="pt4 f4">About {{ .Project.Name }}</h3>
|
||||||
|
<hr class="mv3">
|
||||||
<div id="desc_preview" class="w-100 post-content"></div>
|
<div id="desc_preview" class="w-100 post-content"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -247,14 +292,6 @@
|
||||||
|
|
||||||
let projectForm = document.querySelector("#project_form");
|
let projectForm = document.querySelector("#project_form");
|
||||||
|
|
||||||
projectForm.addEventListener("invalid", function(ev) {
|
|
||||||
switchToTabOfElement(document.body, ev.target);
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
function gotoTab(tabName) {
|
|
||||||
switchTab(document.body, tabName);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////
|
//////////
|
||||||
// Tags //
|
// Tags //
|
||||||
//////////
|
//////////
|
||||||
|
@ -302,6 +339,7 @@
|
||||||
let ownersError = document.querySelector("#owners_error");
|
let ownersError = document.querySelector("#owners_error");
|
||||||
let ownerList = document.querySelector("#owner_list");
|
let ownerList = document.querySelector("#owner_list");
|
||||||
let ownerTemplate = makeTemplateCloner("owner_row");
|
let ownerTemplate = makeTemplateCloner("owner_row");
|
||||||
|
let ownerPreviewTemplate = makeTemplateCloner("owner_preview");
|
||||||
|
|
||||||
addOwnerInput.addEventListener("keypress", function(ev) {
|
addOwnerInput.addEventListener("keypress", function(ev) {
|
||||||
if (ev.which == 13) {
|
if (ev.which == 13) {
|
||||||
|
@ -394,38 +432,52 @@
|
||||||
updateAddOwnerStyles();
|
updateAddOwnerStyles();
|
||||||
});
|
});
|
||||||
|
|
||||||
/////////////////////
|
//////////////////////////////
|
||||||
// Logo management //
|
// Logo / header management //
|
||||||
/////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
const logoMaxFileSize = {{ .LogoMaxFileSize }};
|
const logoMaxFileSize = {{ .LogoMaxFileSize }};
|
||||||
|
const headerMaxFileSize = {{ .HeaderMaxFileSize }};
|
||||||
|
|
||||||
const logoSelector = new ImageSelector(
|
const logoSelector = new ImageSelector(
|
||||||
document.querySelector("#project_form"),
|
document.querySelector("#project_form"),
|
||||||
logoMaxFileSize,
|
logoMaxFileSize,
|
||||||
document.querySelector(".light_logo")
|
document.querySelector(".light_logo"),
|
||||||
|
{
|
||||||
|
onUpdate() {
|
||||||
|
updateCardPreview();
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
function openLogoSelector(e) {
|
function openLogoSelector(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
logoSelector.openFileInput();
|
logoSelector.openFileInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////
|
|
||||||
// Header management //
|
|
||||||
///////////////////////
|
|
||||||
|
|
||||||
const headerMaxFileSize = {{ .HeaderMaxFileSize }};
|
|
||||||
|
|
||||||
const headerSelector = new ImageSelector(
|
const headerSelector = new ImageSelector(
|
||||||
document.querySelector("#project_form"),
|
document.querySelector("#project_form"),
|
||||||
headerMaxFileSize,
|
headerMaxFileSize,
|
||||||
document.querySelector(".header_image")
|
document.querySelector(".header_image"),
|
||||||
|
{
|
||||||
|
onUpdate() {
|
||||||
|
updateCardPreview();
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
function openHeaderSelector(e) {
|
function openHeaderSelector(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
headerSelector.openFileInput();
|
headerSelector.openFileInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateCardPreview() {
|
||||||
|
document.querySelector("#logo_preview").hidden = !logoSelector.url;
|
||||||
|
document.querySelector("#logo_preview img").src = logoSelector.url;
|
||||||
|
document.querySelector("#header_img_preview").style.backgroundImage = `url(${headerSelector.url})`;
|
||||||
|
document.querySelector("#name_preview").innerText = document.querySelector("#project_name").value;
|
||||||
|
document.querySelector("#blurb_preview").innerText = document.querySelector("#description").value;
|
||||||
|
}
|
||||||
|
updateCardPreview();
|
||||||
|
|
||||||
//////////////////
|
//////////////////
|
||||||
// Asset upload //
|
// Asset upload //
|
||||||
//////////////////
|
//////////////////
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<div class="flex justify-between pa3">
|
<div class="flex justify-between pa3">
|
||||||
<div class="flex g3">
|
<div class="flex g3">
|
||||||
{{ if .CanEdit }}
|
{{ if .CanEdit }}
|
||||||
<div class="bg-transparent flex">
|
<div class="project-links">
|
||||||
<a class="ph3 pv2 flex items-center" href="{{ .EditUrl }}"><span class="mr2 flex items-center">{{ svg "edit-line" }}</span>Edit Project</a>
|
<a class="ph3 pv2 flex items-center" href="{{ .EditUrl }}"><span class="mr2 flex items-center">{{ svg "edit-line" }}</span>Edit Project</a>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-100 mw-site-narrow pa3 bg-transparent link-normal flex g3 overflow-hidden" style="margin-top: -4rem">
|
<div class="project-homepage-card">
|
||||||
{{ if .Project.Logo }}
|
{{ if .Project.Logo }}
|
||||||
<a class="flex-shrink-0 flex" href="{{ .Project.Url }}">
|
<a class="flex-shrink-0 flex" href="{{ .Project.Url }}">
|
||||||
<img class="project-card-logo" src="{{ .Project.Logo }}" alt="Project Logo">
|
<img class="project-card-logo" src="{{ .Project.Logo }}" alt="Project Logo">
|
||||||
|
@ -127,7 +127,6 @@
|
||||||
{{ range .RecentActivity }}
|
{{ range .RecentActivity }}
|
||||||
{{ template "timeline_item.html" . }}
|
{{ template "timeline_item.html" . }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
TODO: READ MORE LINK
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue