Skip to content

Commit

Permalink
Add ability to define global colors via settings
Browse files Browse the repository at this point in the history
  • Loading branch information
sunyatasattva committed Feb 25, 2023
1 parent 6eecbf2 commit 3a4c14e
Show file tree
Hide file tree
Showing 5 changed files with 329 additions and 95 deletions.
8 changes: 8 additions & 0 deletions main.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 25 additions & 8 deletions main.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import { Plugin, } from 'obsidian'
import HeatmapCalendarSettingsTab from "settings"

interface CalendarData {
year: number
colors: {
[index: string | number]: {
[index: number]: string
}
}
[index: string | number]: string[]
} | string
entries: Entry[]
showCurrentDayBorder: boolean
defaultEntryIntensity: number
intensityScaleStart: number
intensityScaleEnd: number
}

interface CalendarSettings extends CalendarData {
colors: {
[index: string | number]: string[]
}
}

interface Entry {
date: string
intensity?: number
Expand All @@ -32,7 +38,7 @@ const DEFAULT_SETTINGS: CalendarData = {
}
export default class HeatmapCalendar extends Plugin {

settings: CalendarData
settings: CalendarSettings

/**
* Returns a number representing how many days into the year the supplied date is.
Expand Down Expand Up @@ -74,11 +80,17 @@ export default class HeatmapCalendar extends Plugin {

await this.loadSettings()

this.addSettingTab(new HeatmapCalendarSettingsTab(this.app, this))

//@ts-ignore
window.renderHeatmapCalendar = (el: HTMLElement, calendarData: CalendarData): void => {

const year = calendarData.year ?? this.settings.year
const colors = calendarData.colors ?? this.settings.colors
const colors = typeof calendarData.colors === "string"
? this.settings.colors[calendarData.colors]
? { [calendarData.colors]: this.settings.colors[calendarData.colors], }
: this.settings.colors
: calendarData.colors ?? this.settings.colors

this.removeHtmlElementsNotInYear(calendarData.entries, year)

Expand All @@ -100,7 +112,10 @@ export default class HeatmapCalendar extends Plugin {
intensity: defaultEntryIntensity,
...e,
}
const colorIntensities = colors[e.color] ?? colors[Object.keys(colors)[0]]
const colorIntensities = typeof colors === "string"
? this.settings.colors[colors]
: colors[e.color] ?? colors[Object.keys(colors)[0]]

const numOfColorIntensities = Object.keys(colorIntensities).length

if(minimumIntensity === maximumIntensity && intensityScaleStart === intensityScaleEnd) newEntry.intensity = numOfColorIntensities
Expand Down Expand Up @@ -204,6 +219,7 @@ export default class HeatmapCalendar extends Plugin {
text: e.content,
attr: {
...e.backgroundColor && { style: `background-color: ${e.backgroundColor};`, },
...e.date && { "data-date": e.date, },
},
cls: e.classNames,
parent: heatmapCalendarBoxesUl,
Expand All @@ -218,10 +234,11 @@ export default class HeatmapCalendar extends Plugin {
}

async loadSettings() {
console.log( "heyoh", await this.loadData() );
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData())
}

async saveSettings() {
await this.saveData(this.settings)
}
}
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

162 changes: 162 additions & 0 deletions settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import HeatmapCalendar from "main"
import { App, PluginSettingTab, setIcon, Setting, } from "obsidian"

export default class HeatmapCalendarSettingsTab extends PluginSettingTab {
plugin: HeatmapCalendar

constructor(app: App, plugin: HeatmapCalendar) {
super(app, plugin)
this.plugin = plugin
}

private async addColorMap(color: { key: string, value: string }) {
const isValid = { key: true, value: true, }

if (!color.key) isValid.key = false

const validatedArray = this.validateColorInput(color.value)

if (!validatedArray) isValid.value = false

if (isValid.key && isValid.value) {
this.plugin.settings.colors[color.key] = validatedArray as string[]

await this.plugin.saveSettings()

this.display()
}

return isValid
}

private async deleteColorMap(key: keyof typeof this.plugin.settings.colors) {
delete this.plugin.settings.colors[key]

await this.plugin.saveSettings()

this.display()
}

private displayColorSettings() {
const { containerEl, } = this

containerEl.createEl("h3", { text: "Colors", })
this.displayColorHelp(containerEl)

for (const [key, colors,] of Object.entries(this.plugin.settings.colors)) {
const colorEntryContainer = containerEl.createDiv({
cls: "heatmap-calendar-settings-colors__container",
})

const colorDataContainer = colorEntryContainer.createDiv({
cls: "heatmap-calendar-settings-colors__data-container",
})

colorDataContainer.createEl("h4", { text: key, })

const colorRow = colorDataContainer.createDiv({ cls: "heatmap-calendar-settings-colors__row", })

const colorsContainer = colorRow.createDiv({ cls: "heatmap-calendar-settings-colors__color-container", })

for (const color of colors) {
colorsContainer.createEl("div", {
cls: "heatmap-calendar-settings-colors__color-box",
attr: {
style: `background-color: ${color}`,
},
})

colorsContainer.createEl("pre", {
cls: "heatmap-calendar-settings-colors__color-name",
text: color,
})
}

if (key !== "default") {
const deleteColorButton = colorEntryContainer.createEl("button", {
cls: "mod-warning heatmap-calendar-settings-colors__delete",
})

setIcon(deleteColorButton, "trash")

deleteColorButton.addEventListener("click", () => this.deleteColorMap(key))
}
}

this.displayColorInput(containerEl)
}

private displayColorInput(parent: HTMLElement) {
const inputContainer = parent.createDiv({ cls: "heatmap-calendar-settings-colors__new-color-input-container", })

const colorNameInput = inputContainer.createEl("input", {
cls: "heatmap-calendar-settings-colors__new-color-input-name",
attr: { placeholder: "Color name", type: "text", },
})

const colorValueInput = inputContainer.createEl("input", {
cls: "heatmap-calendar-settings-colors__new-color-input-value",
attr: { placeholder: "Colors array", type: "text", },
})

const addColorButton = inputContainer.createEl("button", {
cls: "mod-cta heatmap-calendar-settings-colors__new-color-button",
})

setIcon(addColorButton, "plus")

addColorButton.addEventListener("click", async () => {
const isValid = await this.addColorMap({
key: colorNameInput.value,
value: colorValueInput.value,
})

this.reportInputValidity(colorNameInput, isValid.key, "Please input a name for your color")
this.reportInputValidity(colorValueInput, isValid.value, "Color is not a valid JSON array of colors")
})
}

private displayColorHelp(parent: HTMLElement) {
parent.createEl("p", {
text: "Add lists of colors which will be globally available on your heatmaps.",
})
parent.createEl("p", {
text: "You can use those colors by referencing their name in your heatmap render settings.",
})
}

private reportInputValidity(input: HTMLInputElement, isValid: boolean, msg: string) {
if (!isValid) {
input.classList.add("has-error")
input.setCustomValidity(msg)
} else input.setCustomValidity("")

input.reportValidity()
}

private validateColorInput(value: string) {
const colorRegex = /^(#[0-9a-f]{3,6}|rgba?\(\s*\d+%?\s*,\s*\d+%?\s*,\s*\d+%?\s*(,\s*\d+(\.\d+)?%?)?\s*\))$/i;

try {
const data: string[] = JSON.parse(value)

if (!Array.isArray(data)) return false

return data.every(color => colorRegex.test(color)) ? data : false
} catch (e) {
return false
}
}

display() {
const { containerEl, } = this

containerEl.empty()

containerEl.createEl("h2", { text: "Heatmap Calendar Settings", })

this.displayColorSettings()

console.log( "settings", this.plugin.settings )
}
}
Loading

0 comments on commit 3a4c14e

Please sign in to comment.